/**
 * 文档处理器
 */
function sProcessor(option) {
    /**
     * 句柄
     */
    var handleList = [];

    /**
     * 文本缩放比
     */
    var scale = 1;

    /**
     * 分页对象
     */
    var pageList = new sPageList();

    /**
     * 当前页
     */
    var curPage = null;

    /**
     * 分页参数
     */
    var pageOption = {};

    /**
     * 分页页面布局
     */
    var layout = null;

    /**
     * 文档
     */
    var document = null;
    
    /**
     * 排版引擎集合
     */
    var renderList = [];

    /**
     * 当前的range对象
     */
    var range = null;

    /**
     * 查找区域引用对象
     */
    var finding = {};

    /**
     * 转换器
     */
    var converter = new sConverter();

    /**
     * 偏移量工具
     */
    var ost = new sOffsetUtil();

    /**
     * 格式化工具
     */
    var fmt = new sFormatUtil();

    /**
     * 图层管理器
     */
    var plm = new sPaintLayerManager();

    /**
     * 绑定类
     */
    var bindMethods = new sBindMethods();

    /**
     * 粘滞状态
     */
    var sticky = false;

    /**
     * 鼠标左键按下状态
     */
    var mouseLeftDown = false;

    /**
     * 最近一次定位生成的事件目标对象
     */
    var lme = null;

    /**
     * 差异化工具
     */
    var diffUtil = option ? option.diffUtil : null;

    /**
     * 脚本函数
     */
    var scriptFuncs = option ? option.scriptFuncs : null;

    /**
     * 动作栈表
     */
    var ACTIONS = null;

    /**
     * 事件管理器
     */
    var events = null;

    /**
     * 配置信息
     */
    var setting = null;
    
    /**
     * 页面区域
     */
    var areas = ["body", "head", "foot"];

    /**
     * 定位时，光标的原子偏移添加值
     */
    var DRIFT_LEN = 2;

    /**
     * 当前鼠标是否作用在选择区域
     */
    var onSel = false;

    /**
     * 是否作用在页眉页脚
     */
    var onHf = false;

    /**
     * 关联方法
     * @param {*} name 方法名
     * @param {*} method 方法引用
     * @param {*} context 方法执行上下文，可选
     */
    this.link = function(name, method, context){
        bindMethods.link(name, method, context);
    }

    /**
     * 添加设备句柄
     * @param {*} handle 句柄
     * @param {*} index 指定加入的序号
     */
    this.addHandle = function (handle, index) {
        if(typeof(index) === "undefined"){
            handleList.push(handle);
        }else{
            handleList[index] = handle;
        }
    }

    /**
     * 删除设备句柄
     * @param {*} index 按指定的序号删除
     */
    this.removeHandle = function(index) {
        renderList[handleList[index]] = null;
        handleList[index] = null;
    }

    /**
     * 重置所有属性
     */
    this.reset = function() {
        handleList = [];
        renderList = [];
        finding = {};

        sticky = false;
        curPage = null;

        pageList = new sPageList();
        plm = new sPaintLayerManager();
        ACTIONS = new sActions({
            maxSize: setting ? setting.actionMaxSize : null,
            leaveTrace: setting ? setting.leaveTrace : false
        });

        events = new sEvents();
    }

    /**
     * 获取事件管理器
     * @returns 
     */
    this.getEvents = function(){
        return events;
    }

    /**
     * 设置文档
     * @param {*} doc 
     */
    this.setDocument = function(doc) {
        document = doc;
    }

    /**
     * 设置文本缩放比
     * @param {*} ratio 
     */
    this.setScale = function(ratio) {
        scale = ratio;
    }

    /**
     * 获取分页总数
     */
    this.getPageSize = function() {
        return pageList.getPageSize();
    }

    /**
     * 获取页面包围盒
     * @param {*} type
     */
    this.getPageRect = function(type) {
        return pageList.getFirstPage().getBoundRect(type);
    }

    /**
     * 获取分页信息
     * @returns 
     */
    this.getPageList = function() {
        return pageList;
    }

    /**
     * 根据数据构建画面
     * @param {*} data 
     * @param {*} opt
     * 
     * @returns false 构建失败 true 构建成功
     */
    this.build = function (data, opt) {
        if(!validateData.call(this, data)) return;
        
        opt = opt ? opt : {};

        var onlyFormat = opt.onlyFormat;
        
        if(!onlyFormat){
            pageOption = {};
            opt.pageOption = pageOption;

            setting = bindMethods.invoke("getSetting");
            ACTIONS = new sActions({
                maxSize: setting.actionMaxSize,
                leaveTrace: setting.leaveTrace
            });

            layout = getPageLayout.call(this, data, opt);
            opt.layout = layout;
        }else{
            opt.pageOption = {};
            opt.layout = getPageLayout.call(this, data, opt);
        }
        
        var root = cleanData.call(this, data);

        new Promise((resolve)=>{
            opt.callback = (args)=>{
                if(args !== opt.layout.body || onlyFormat) return;
                resolve();
            };

            format.call(this, root, opt);

            if(opt.afterFormat){
                opt.afterFormat(opt);
            }
        }).then(()=>{
            return new Promise((resolve)=>{
                opt.callback = (args)=>{
                    resolve();
                };

                paint.call(this, {...opt, range: getInitRange()});
            });
        }).then(()=>{
            return new Promise(()=>{
                initLocateCaret();
                contentChange();

                if(opt.load){
                    opt.load();
                }
            });
        })

        return true;
    }

    /**
     * 获取初始的呈现页范围
     * @returns 
     */
    var getInitRange = function(){
        let size = document.getMaxRenderSize();
        let range = [];
        for(let i = 1; i <= size; i++){
            range.push(i);
        }
        return range;
    }

    /**
     * 初始化定位光标
     */
    var initLocateCaret = function(){
        var sEvt = bindMethods.invoke("createMouseEvent");
        var row = pageList.getFirstPage().getFirstRow("body");
        var element = row.getFirstVisualElement();
        var boundRect = row.getElementBoundRect(element);
        
        sEvt.offset = {
            left: boundRect.left,
            top: row.getBoundRect().top + boundRect.top
        }
        sEvt.target = pageList.getFirstPage().search(sEvt.offset);

        setLastPmdEvt(sEvt);
        curPage = pageList.getFirstPage();
        
        renderList[curPage.getIndex()].locate(sEvt, {relocate: relocate});
    }

    /**
     * 校验数据
     */
    var validateData = function(data){
        if(!data) return false;
        return true;
    }

    /**
     * 清洗数据，提高加载效率
     * 例如：对于文本内容过长的单个对象进行拆分
     * @param {*} data 
     */
    var cleanData = function(data){
        return data;
    }

    /**
     * 获取分页布局
     * @param {*} root 
     * @param {*} opt
     * @returns 
     */
    var getPageLayout = function(root, opt){
        var areas = ["sPageHead", "sPageFoot", "sPageBody"];
        var positions = ["head", "foot", "body"];
        var layout = {};
        var index = -1;
        var paragraphs = {};

        for(var i = 0; i < root.children.length; i++){
            var element = root.children[i];
            
            index = areas.indexOf(element._sType);

            if(index > -1){
                var position = positions[index];
                layout[position] = element;
                paragraphs[position] = [];

                var ind = 0;
                parseParagraph([element], ind, paragraphs[position]);

                areas.splice(index, 1);
                positions.splice(index, 1);
            }

            if(areas.length == 0){
                break;
            }
        }
        
        opt.pageOption.paragraphs = paragraphs;

        return layout;
    }

    /**
     * 解析段落
     * @param {*} elements 
     * @param {*} index 
     * @param {*} paragraphs 
     */
    var parseParagraph = function(elements, index, paragraphs){
        for(var i in elements){
            var element = elements[i];
            if(!element._sType) continue;

            element.__paragraphIndex = index;

            if(element._sType == "sParagraph"){
                paragraphs[index] = element;
                element.__paragraphIndex = index;
                index++;
            }

            if(element.children && element._sType != "sLayer"){
                parseParagraph(element.children, ++index, paragraphs);
            }
        }
    }

    /**
     * 内容排版
     * @param {*} root 
     * @param {*} opt
     */
    var format = function(root, opt){
        opt.pageOption.style = {...root.style, ...opt.paperSize};
        opt.pageOption.traceDisplay = setting.traceDisplay;

        opt.pageList = opt.pageList 
            ? opt.pageList 
            : pageList;
        
        opt.pageList.setAllProps(root);

        var render = new sLayoutEngine(
            new sPainter(opt.canvas 
                ? opt.canvas 
                : document.getCanvas(handleList[0])),
            opt.pageList.insertPage(opt.pageOption),
            scale * (opt.ratioTime ? opt.ratioTime : 1),
            { setting: setting }
        );

        if(opt && opt.formatPageChange){
            opt.formatPageChange(opt.pageList.getPageSize());
        }

        formatHead.call(this, render, opt);
        formatFoot.call(this, render, opt);
        formatBody.call(this, render, opt);
    }

    /**
     * 循环遍历元素排版
     * @param {*} index 
     * @param {*} area 
     * @param {*} rect 
     * @param {*} render 
     * @param {*} opt 
     */
    var loopFormat = (index, area, rect, render, opt)=>{
        var child = null;
        for(var i = index; i < area.children.length; i++){
            child = area.children[i];

            opt.prevElement = area.children[i - 1];
            opt.nextElement = area.children[i + 1];

            render.linkElement(child, area.children[i + 1]);

            if(isExceedMaxLength(child)){
                var txts = splitLongText(child.innerText, child.style, child.__paragraphIndex);
                for(var j in txts){
                    generatePage.call(this, render, txts[j], rect, opt);
                }
            }else{
                generatePage.call(this, render, child, rect, opt);
            }

            //如果该元素没有被排版，则将该元素的前一个元素和后一个元素链接
            render.unlinkElement(child);
        }

        if(opt.callback){
            opt.callback(area);
        }
    }

    /**
     * 页体排版
     * @param {*} render 
     * @param {*} opt 
     */
    var formatBody = function(render, opt){
        opt.layoutType = "body";

        var body = opt.layout.body;

        if(!body || body.style && body.style.display == "none") return;

        var rect = opt.pageList.getLastPage().getBoundRect(opt.layoutType, true);
        var index = 0;
        
        loopFormat.call(this, index, body, rect, render, opt);
    }

    /**
     * 页眉排版
     */
    var formatHead = function(render, opt){
        opt.layoutType = "head";

        var head = opt.layout.head;

        if(!head || !isLayoutVisible(opt.layoutType) || !head.children) return;

        var rect = opt.pageList.getLastPage().getBoundRect(opt.layoutType, true);
        var index = 0;

        loopFormat.call(this, index, head, rect, render, opt);
    }

    /**
     * 页脚排版
     */
    var formatFoot = function(render, opt){
        opt.layoutType = "foot";

        var foot = opt.layout.foot;

        if(!foot || !isLayoutVisible(opt.layoutType) || !foot.children) return;

        var rect = opt.pageList.getLastPage().getBoundRect(opt.layoutType, true);
        var index = 0;

        loopFormat.call(this, index, foot, rect, render, opt);
    }

    /**
     * 生成页面并排版
     * @param {*} render 
     * @param {*} element 
     * @param {*} parentRect 
     * @param {*} opt 
     * @returns 
     */
    var generatePage = function(render, element, parentRect, opt){
        var type = opt && opt.layoutType;
        var newpage = 0;

        try{
            switch(element._sType){
                case "sText":
                    newpage = render.textFormat(element, parentRect, type);
                    break;
                case "sParagraph":
                    newpage = render.paragraphFormat(element, parentRect, type);
                    break;
                case "sBreakline":
                    newpage = render.breaklineFormat(element, type);
                    break;
                case "sLayer":
                    newpage = render.layerFormat(element, type);
                    break;    
                case "sInputBegin":
                case "sInputEnd":
                    newpage = render.inputAreaFormat(element, parentRect, type, opt);
                    break;
                case "sTable":
                    newpage = render.tableFormat(element, parentRect, type, opt);
                    break;
            }
        }catch(e){
            console.error(e);
        }

        //需新增分页
        if(newpage > 0 && type == "body"){
            //引用上一页页眉、页脚
            opt.pageOption.head = opt.pageList.getLastPage().getArea("head");
            opt.pageOption.foot = opt.pageList.getLastPage().getArea("foot");

            render.bindPage(opt.pageList.insertPage(opt.pageOption));

            //页面变化通知
            if(opt && opt.formatPageChange){
                opt.formatPageChange(opt.pageList.getPageSize());
            }

            opt.layoutType = "body";

            var parentRect = opt.pageList.getLastPage().getBoundRect(opt.layoutType, true);

            //当newpage == 9时，一般是分页符排版返回的结果
            if(newpage < 9){
                return generatePage(render, element, parentRect, opt);
            }else{
                return 0;
            }
        }

        return newpage;
    }

    /**
     * 打印
     */
    this.print = function(opt){
        var range = pageList.getAllRange();
        paint.call(this, {
            print: true,
            range: range,
            ...opt
        });
    }

    /**
     * 内容绘制
     * @param {*} opt 
     */
    var paint = function(opt){
        opt = opt ? opt : {};
        
        opt.setting = setting;
        opt.plm = opt.plm ? opt.plm : plm;

        if(!opt.zoomScale){
            opt.zoomScale = document.getRenderParam().zoomScale;
        }

        if(opt.isHeadEditable != null){
            pageList.setHeadEditable(opt.isHeadEditable);
        }

        var insertPage = false;
        var rownum = 0;
        var ratioTime = opt.ratioTime ? opt.ratioTime : 1;

        var empty = isEmptyHeadFoot();
        var pages = opt.pageList ? opt.pageList : pageList;
        var pageSize = pages.getPageSize();
        var lastParagraphIndex = {
            head: null,
            foot: null,
            body: null
        };

        pages.forEach((page, pageIndex)=>{
            if(opt.range.indexOf(pageIndex) < 0){ 
                rownum += page.getRowCount("body");
                return; 
            };

            console.log("绘制页面：" + pageIndex);

            initHandleList(pageIndex);
            
            if(isHandleNotExist.call(this, pageIndex)){
                document.insertPage(null, {
                    pageIndex: pageIndex
                });
                insertPage = true;
            }

            var canvas = null;
            var render = null;

            if(opt.print){
                render = new sLayoutEngine(new sPainter(opt.canvas), page, scale * ratioTime, opt);
            }else{
                canvas = document.getCanvas(handleList[pageIndex - 1]);
                render = new sLayoutEngine(new sPainter(canvas), page, scale, opt);
    
                renderList[pageIndex] = render;
            }

            render.getPainter().clear();

            //清除相关图层
            clearPaintLayer(opt.plm, pageIndex);

            var option = null;
            var pIndex = null;

            //批注区域
            var annotationProp = getAnnotationProp(page);

            //绘制水印
            render.getPainter().drawWatermark(
                pageList.getWatermark(), 
                page.getBoundRect(), 
                pageIndex, 
                annotationProp
            );

            //绘制底纹
            render.getPainter().drawTexture(
                pageList.getTexture(), 
                page.getBoundRect(), 
                pageIndex,
                annotationProp
            );

            //绘制行内元素
            page.forEach((row, index, type)=>{
                pIndex = pageIndex;
                option = {
                    type: "body",
                    annotationProp: annotationProp,
                    elementBorderDisplay: setting.elementBorderDisplay,
                    pageSize: pageSize
                };

                if(type == "head" || type == "foot"){
                    if(empty[type]) return;
                    if(isOutRectForHeadFoot(page, type, row)) return;
                    pIndex = 1;
                    option.type = type;
                    option.pageIndex = pageIndex;
                }
                
                if(setting.lineNumberDisplay){
                    render.getPainter().drawRowNumber(row, type == "body" ? ++rownum : null);
                }
                
                if(setting.rowBorderDisplay){
                    render.getPainter().drawRowBorder(row.getBoundRect());
                }
                
                option.isParagraphEnd = row.isEndWithParagraph();

                //绘制差异行
                let diffRows = pages.getDiffRow(index, pageIndex, type);
                if(diffRows){
                    let diffRow = null;
                    for(var i in diffRows){
                        diffRow = diffRows[i];
                        diffRow.row.forEach((element)=>{
                            paintElement(element, render, diffRow.row, index, pIndex, type, {...option});
                        });
                        paintDiffRow.call(this, diffRow, render, { backDisplay: true, minus: true });
                    }

                    paintDiffRow.call(this, {row: row}, render, { lastest: true, plus: true });
                }

                //绘制正文行
                row.forEach((element)=>{
                    let opt = {...option};
                    if(lastParagraphIndex[type] != element.__paragraphIndex){
                        opt.paragraph = pages.getParagraph(element.__paragraphIndex, type);
                        lastParagraphIndex[type] = element.__paragraphIndex;
                    }
                    paintElement(element, render, row, index, pIndex, type, opt);
                }, {
                    ignoreInvisible: true, 
                    containParagraph: true
                });
            });

            //绘制绝对定位元素(目前只支持层元素)
            page.forEachForAbsolute((element, type, index)=>{
                render.getPainter().drawLayer(element, null, pageIndex);
            });

            if(insertPage || opt.highlightFindZone){
                paintFindFragment.call(this, render, pageIndex);
                startSelection.call(this, null, { notInvalidate: true });
            }

            if(!opt.print){
                render.getPainter().drawLayout(page, {
                    head: isLayoutVisible("head"),
                    foot: isLayoutVisible("foot"),
                    annotationProp: annotationProp,
                    isHeadEditable: pageList.isHeadEditable()
                });
            }

            render.getPainter().drawPaintLayer();

            if(opt.afterPaintPage){
                opt.afterPaintPage({
                    pageIndex: pageIndex
                });
            }
        })
        
        bindMethods.invoke("formatPageChange", pageList.getPageSize());

        for(var i in handleList){
            if(!pageList.contain(handleList[i])){
                bindMethods.invoke("removePage", handleList[i]);
            }
        }

        if(opt.callback){
            opt.callback();
        }
    }

    /**
     * 清除相关图层
     * @param {*} plm 
     * @param {*} pageIndex 
     */
    var clearPaintLayer = function(plm, pageIndex){
        plm.clear(ssDict.sPaintLayerLevel.CONTEXT_BACKGROUND_IMAGE, pageIndex);
        plm.clear(ssDict.sPaintLayerLevel.CONTEXT_BACKGROUND, pageIndex);
        plm.clear(ssDict.sPaintLayerLevel.PAGE_BACKGROUND_IMAGE, pageIndex);
        plm.clear(ssDict.sPaintLayerLevel.PAGE_BACKGROUND, pageIndex);
        plm.clear(ssDict.sPaintLayerLevel.ELEMENT_BACKGROUND, pageIndex);
        plm.clear(ssDict.sPaintLayerLevel.ELEMENT_CONTENT, pageIndex);
        plm.clear(ssDict.sPaintLayerLevel.LAYER_ZONE, pageIndex);
        plm.clear(ssDict.sPaintLayerLevel.HIGHLIGHT, pageIndex);
    }

    /**
     * 获取批注区域相关属性
     * @param {*} page 
     */
    var getAnnotationProp = function(page){
        var boundRect = page.getBoundRect();
        var renderParam = document.getRenderParam();
        var annotationWidth = setting.annotation.width * renderParam.ratio;
        var rect = {
            left: boundRect.width - annotationWidth,
            top: 0,
            width: annotationWidth,
            height: boundRect.height
        };

        return {
            boundRect: rect,
            pageRect: page.getBoundRect(),
            pagePadding: page.getPadding(),
            annotationWidth: annotationWidth
        };
    }

    /**
     * 绘制元素
     * @param {*} element 
     * @param {*} render 
     * @param {*} row 
     * @param {*} index 
     * @param {*} pageIndex 
     * @param {*} type
     * @param {*} option 
     */
    var paintElement = function(element, render, row, index, pageIndex, type, option){
        if(element.__boundRect){
            option.boundRect = render.getPainter().translateElementRectTop(element, 
                row.getBoundRect().top, index, pageIndex);
        }

        filterColor(type, element, option);

        switch(element._sType){
            case "sText":
                render.getPainter().drawText(element, index, pageIndex, option);
                break;
            case "sLayer":
                render.getPainter().drawLayer(element, index, pageIndex, option);
                break;
            case "sTable":
                option.cellGridDisplay = setting.cellGridDisplay;
                render.getPainter().drawTable(element, index, pageIndex, option);
                break;
            case "sParagraph":
                render.getPainter().drawParagraph(element, index, pageIndex, option);
                break;
            case "sBreakline":
                render.getPainter().drawBreakline(element, index, pageIndex, option);
                break;
            case "sInputBegin":
            case "sInputEnd":
                render.getPainter().drawInputArea(element, index, pageIndex, option);
                break;
        }
    }

    /**
     * 绘制差异行
     * @param {*} row 
     * @param {*} render 
     * @param {*} option
     */
    var paintDiffRow = function(diffRow, render, option){
        option = option ? option : {};

        if(diffRow.diffRects){
            option.diffRects = diffRow.diffRects;
        }

        render.getPainter().drawDiffRow(diffRow.row, option);

        // 文本比较
        // if(!option.lastest){
        //     var myself = this;
        //     diffRow.addEventListener("paint", function(opt){
        //         let proc = null;
        //         let offset = null;
                
        //         let point = -1;
        //         let start = 0;
        //         let end = 0;
    
        //         let left = 0;
        //         let top = 0;
        //         let width = 0;
        //         let height = 0;
                
        //         let index = 0;
        //         let boundRects = [];
        //         let pageRange = [];
        //         let text = this.content.text;
    
        //         for(var i = 0; i < this.diffProc.length; i++){
        //             proc = this.diffProc[i];
    
        //             if(!proc.removed && !proc.added) {
        //                 point += proc.count;
        //                 continue;
        //             }
    
        //             start = point < 0 ? 0 : point;
        //             end = point + proc.count;
                    
        //             width = 0;
        //             left = -1;
    
        //             for(var j = index; j < this.content.offsets.length; j++){
        //                 offset = this.content.offsets[j];
    
        //                 if(pageRange.indexOf(offset.pageIndex) < 0){
        //                     pageRange.push(offset.pageIndex);
        //                 }
    
        //                 if(start >= offset.start - 1 && start < offset.end){
        //                     let element = this.content.elements[j];
        //                     let rect = element.__boundRect[offset.pageIndex][offset.rowIndex];
        //                     let elText = element.__texts[offset.pageIndex][offset.rowIndex];
                            
        //                     if(left < 0){
        //                         metr = render.measureText(element, 
        //                             elText.substring(0, point + 1 - offset.start), {new: true});
        //                         left = rect.left + metr.width;
        //                     }
    
        //                     if(end > offset.end){
        //                         metr = render.measureText(element, 
        //                             text.substring(point + 1, offset.end + 1), {new: true});
    
        //                         width += metr.width;
        //                         point = offset.end;
        //                         start = offset.end;
    
        //                         continue;
        //                     }else{
        //                         metr = render.measureText(element, 
        //                             text.substring(point + 1, end + 1), {new: true});
        //                         width += metr.width;
        //                     }
    
        //                     height = height < rect.height ? rect.height : height;
    
        //                     let temp = rect.top - metr[metr.FONT_ASCENT];
        //                     top = top > 0 && top < temp ? top : temp;
    
        //                     top += diffRow.row.getBoundRect().top;
    
        //                     boundRects.push({
        //                         left: left,
        //                         top: top,
        //                         width: width,
        //                         height: height
        //                     });
    
        //                     index = j;
        //                     break;
        //                 }
        //             }
    
        //             point += proc.count;
        //         }
                
        //         diffRow.diffRects = boundRects;
    
    
        //         myself.invalidate({range: pageRange});
        //     }, { once: true });
        // }
    }

    /**
     * 文本元素超过最大长度
     * @returns 
     */
    var isExceedMaxLength = function(element){
        return element._sType == "sText" && 
            element.innerText && element.innerText.length > MAX_TEXT_LENGTH;
    }

    /**
     * 判断当前行是否超过head、foot限制的高度范围
     * @param {*} page 
     * @param {*} type 
     * @param {*} row 
     */
    var isOutRectForHeadFoot = function(page, type, row){
        var rowRect = row.getBoundRect();
        var rect = null;

        if(type == "head"){
            rect = page.getBoundRect(type, true);
            return rowRect.top + rowRect.height > rect.top + rect.height;
        }else{
            rect = page.getBoundRect(type, false);
            return rowRect.top < rect.top;
        }
    }

    /**
     * 判断页眉、页脚内容是否为空
     * @returns 
     */
    var isEmptyHeadFoot = function(){
        var empty = {
            head: true,
            foot: true
        };

        var page = pageList.getFirstPage();
        var areas = ["head", "foot"];

        for(var j in areas){
            var area = page.getArea(areas[j]);

            var isEmpty = area.getRowCount() == 0 || 
                (area.getRowCount() == 1 &&
                 area.getRowList()[0].getElementList().length == 0);

            if(!isEmpty){
                isEmpty = true;

                if(area.getRowCount() > 1){
                    isEmpty = false;
                }else{
                    var elementList = area.getRowList()[0].getElementList();
                    for(var i in elementList){
                        if(elementList[i].innerText != "" && 
                        elementList[i].innerText != null){
                            isEmpty = false;
                            break;
                        }else if(elementList[i]._sType != "sText" &&
                            elementList[i]._sType != "sParagraph"){
                            isEmpty = false;
                            break;
                        }
                    }
                }
            }

            empty[areas[j]] = isEmpty && !pageList.isHeadEditable();
        }

        return empty;
    }

    /**
     * 颜色滤镜
     * @param {*} type 
     * @param {*} element 
     * @param {*} option 
     * @returns 
     */
    var filterColor = function(type, element, option){
        if(!element.style || element.style.display == "none") return;

        if((pageList.isHeadEditable() && (type == "head" || type == "foot")) ||
          (!pageList.isHeadEditable() && type == "body")) return;

        var color = element.style && element.style.color
            ? element.style.color 
            : "#000";

        var backgroundColor = element.style.backgroundColor;
        backgroundColor = !backgroundColor ? "#fff" : backgroundColor;

        var borderColor = element.style.borderColor;
        borderColor = !borderColor ? "#000" : borderColor;

        option.color = converter.lightOrDarkColor(0.6, color);
        option.backgroundColor = converter.lightOrDarkColor(0.5, backgroundColor);
        option.borderColor = converter.lightOrDarkColor(0.5, borderColor);
        option.imageFilterColor = "#eeddddb3";
    }

    /**
     * 指定类型布局是否可见
     * @param {*} type 布局类型 
     * @returns 
     */
    var isLayoutVisible = function(type){
        var l = layout[type];
        return !(!l || (l.style && l.style.display == "none"));
    }

    /**
     * 初始化句柄
     * @param {*} pageIndex 
     */
    var initHandleList = function(pageIndex){
        if(typeof(handleList[pageIndex - 1]) === "undefined"){
            handleList[pageIndex - 1] = null;
        }
    }

    /**
     * 对应的句柄是否存在
     * @param {*} pageIndex 
     * @returns 
     */
    var isHandleNotExist = function(pageIndex){
        return pageIndex > handleList.length || handleList[pageIndex - 1] === null;
    }

    /**
     * 重新渲染
     * @param {*} opt 
     */
    this.invalidate = function(opt){
        paint.call(this, opt);
    }

    /**
     * 分发事件
     * @param {*} sEvt 事件对象
     */
    this.dispatchEvent = function(sEvt) {
        if(sEvt.handle){
            var page = pageList.getPage(sEvt.handle);
            if(!page) return;
            curPage = page;
        }

        if(!curPage) return;

        sEvt.pageList = pageList;
        var render = renderList[curPage.getIndex()];
        
        switch(sEvt.eventType){
            case "mousedown":
                if(sEvt.nativeEvt.button == 0){
                    mouseLeftDown = true;
                }

                startControl.start(sEvt.eventType);
                
                sEvt.target = curPage.search(sEvt.offset);

                if(sEvt.target.position != "body" && !pageList.isHeadEditable()){
                    onHf = false;
                    setTimeout(()=>{
                        if(onHf) return;
                        mousedowndp.call(this, sEvt, render, curPage);
                    }, 200);
                }else{
                    mousedowndp.call(this, sEvt, render, curPage);
                }

                break;
            case "mouseup":
                mouseLeftDown = false;
                startResize.call(this, sEvt, render);
                if(!sticky){
                    setSelection.call(this, sEvt);
                    if(onSel && sEvt.nativeEvt.button == 0){
                        invalidateSelection.call(this);
                        render.locate(lme, {notDoSelection: true});
                    }
                }
                processMouseUp.call(this, sEvt, render);
                break;
            case "mousemove":
                processCursor.call(this, sEvt, render, curPage);
                if(!startControl.canStart("mousedown", 20)) return;
                if(mouseLeftDown){
                    setScroll(sEvt, 1);
                    if(processResize(sEvt, false, render)) return;
                    locateTarget.call(this, sEvt, curPage, render);
                }
                break;
            case "mousewheel": 
                processZoom.call(this, sEvt, curPage, render);
                break;
            case "click":
                break;
            case "dblclick":
                sEvt.target = curPage.search(sEvt.offset);
                setEditable(sEvt);
                autoSelect.call(this, sEvt, render);
                break;
            case "keydown":
                if(!setSticky(sEvt, true)){
                    processDirection.call(this, sEvt, render);
                    processCrud.call(this, sEvt, render);
                }
                break;
            case "keyup":
                setSticky(sEvt, false);
                break;
        }
    }

    /**
     * 鼠标按下事件处理函数
     * @param {*} sEvt 
     * @param {*} render 
     * @param {*} curPage 
     * @returns 
     */
    var mousedowndp = function(sEvt, render, curPage){
        if(!canEditPass(sEvt)) return;
        if(processResize.call(this, sEvt, true, render)) return;

        if(isOnSelection(sEvt, render)) {
            setLastPmdEvt(sEvt);
            return;
        }

        processEleProp.call(this, sEvt, render);
        processSelect.call(this, sEvt, render, curPage);
    }

    /**
     * 事件启动控制器
     */
    var startControl = {
        map: {},
        start: function(e){
            if(!this.map[e]){
                this.map[e] = {};
            }
            this.map[e].startTime = (new Date()).getTime();
        },
        canStart: function(e, interval){
            if(this.map[e] && this.map[e].startTime){
                if((new Date()).getTime() - 
                    this.map[e].startTime < interval){
                    return false;
                }
                this.map[e].startTime = null;
            }
            return true;
        }
    }

    /**
     * 处理鼠标指针显示状态
     * @param {*} sEvt 
     * @param {*} render
     * @param {*} curPage
     */
    var processCursor = function(sEvt, render, curPage){
        if(!sEvt.offset) return;

        var target = curPage.search(sEvt.offset, null, {
            isHeadEditable: pageList.isHeadEditable()
        });
        if(!target) return;

        var isActive = (sEvt.layerResize && sEvt.layerResize.isActive()) ||
            (sEvt.cellResize && sEvt.cellResize.isActive())
        if(isActive) return;

        if(target.touchCellBorder){
            document.setCursor(target.touchCellBorder == "bottom" 
                ? "row-resize" : "col-resize", "canvas");
        }else if(target.ref._sType == "sLayer"){
            document.setCursor("pointer", "canvas");
        }else{
            if(target.touchTable){
                sEvt.target = target;
            }
            document.setCursor("text", "canvas");
            processEleProp.call(this, sEvt, render);
        }

        //鼠标移动到批注区域
        if(target.invalidteAnnotation){
            this.invalidate({range: [target.pageIndex]});
        }
    }

    /**
     * 处理页面的放大缩小
     * @param {*} sEvt 
     */
    var processZoom = function(sEvt, page, render){
        if(!sEvt.ctrl || sEvt.eventType != "mousewheel") return;
        if(!lme || !lme.target) return;

        var target = lme.target;
        var lookResult = pageList.lookup(target.position, target);

        sEvt.target = lookResult;
        sEvt.offset = lookResult.boundRect;

        var next = ost.extractOffset(lookResult.offset, true);

        render.locate(sEvt, { 
            relocate: relocate, 
            locateContentIndex:  next.contentIndex
        });
    }

    /**
     * 当前页码
     */
    var currentPageIndex = null;

    /**
     * 获取当前页码
     * @returns 
     */
    this.getCurrentPageIndex = function(){
        return currentPageIndex ? currentPageIndex : 1;
    }

    /**
     * 处理对内容的选择
     * @param {*} sEvt 
     * @param {*} render 
     * @param {*} curPage 
     */
    var processSelect = function(sEvt, render, curPage){
        if(sticky){
            if(!isSelection(sEvt)){
                setSelection.call(this, lme, 1, {notResetStartOffset: true});
                setSelection.call(this, sEvt, 2);
                render.locate(lme, { relocate: relocate });
            }
            locateTarget.call(this, sEvt, curPage, render);
        }else{
            setSelection.call(this, sEvt);
            setSelection.call(this, sEvt, 1);
            render.locate(sEvt, { relocate: relocate });
            if(sEvt.target){
                setLastPmdEvt(sEvt);
            }
        }

        if(!currentPageIndex || (sEvt.target && currentPageIndex != sEvt.target.pageIndex)){
            currentPageIndex = sEvt.target.pageIndex;
            pageChange(currentPageIndex);
        }
    }

    /**
     * 当前页改变事件任务
     */
    var pageChangeTask = null;

    /**
     * 当前页改变事件
     */
    var pageChange = function(pageIndex){
        if(pageChangeTask){
            clearTimeout(pageChangeTask);
            pageChangeTask = null;
        }

        setTimeout(()=>{
            bindMethods.invoke("pageChange", pageIndex);
        }, 50);
    }

    /**
     * 处理元素属性
     * @param {*} sEvt 
     * @param {*} render 
     */
    var processEleProp = function(sEvt, render) {
        if(sEvt.tableOperator){
            sEvt.tableOperator.blur();
        }

        if(!sEvt.target) {
            sEvt.target = lme && lme.target;
            if(!sEvt.target){
                return;
            }
        };

        var type = sEvt.target.position;
        var pageIndex = sEvt.target.position == "body" 
            ? sEvt.target.pageIndex 
            : 1;

        if(sEvt.target.next){
            var arr = ost.splitOffset(sEvt.target, true)
            var cellOffset = arr[arr.length - 1];
            var table = cellOffset.table;

            var offset = arr[arr.length - 2];
            
            if(table && !isDocReadOnlyOrForm() && 
               table.getColCount() > 0 && table.getRowCount() > 0){
                var tableRect = null;

                //holder表示该表格存在持有元素(layer)
                if(sEvt.target.holder){
                    tableRect = table.__boundRect[table.__boundRect.length - 1];
                    tableRect = tableRect[tableRect.length - 1];
                }else{
                    tableRect = table.__boundRect[pageIndex][offset.rowIndex];
                }

                var tableOffset = render.locateElementOffset(offset, table);
                var rect = {
                    left: sEvt.baseOffset.left + tableOffset.left / sEvt.ratio,
                    top: sEvt.baseOffset.top + tableOffset.top / sEvt.ratio,
                    width: tableRect.width / sEvt.ratio,
                    height: (tableRect.height + 4) / sEvt.ratio,
                };
        
                var rows = [];
                var row = null;
                var eleOffset = null;
        
                for(var i = 0; i < table.getRows().length; i++){
                    row = table.getRows()[i];
                    eleOffset = getTableLayoutOffsetByPage(row, pageIndex);
        
                    if(!eleOffset) continue;

                    rows.push({
                        left: eleOffset.left / sEvt.ratio,
                        top: (eleOffset.top + 1) / sEvt.ratio,
                        width: eleOffset.width / sEvt.ratio,
                        height: eleOffset.height / sEvt.ratio,
                        index: i
                    });
                }

                var row = null;
                var cell = null;
                var cols = [];
        
                for(var i = 0; i < table.getColumns().length; i++){
                    row = table.getRows(cellOffset.tableRowIndex);
                    if(!row) continue;
                    
                    cell = row.getCells(i);
                    if(!cell) continue;

                    if(cell.style.display == "none"){
                        var spanCell = render.getSpanCell(table, cellOffset.tableRowIndex, i);
                        if(!spanCell || i > spanCell.getColIndex()) continue;

                        cell = spanCell.getRef();
                        i = spanCell.getColIndex() + spanCell.getColspan() - 1;
                    }
                    eleOffset = getTableLayoutOffsetByPage(cell, pageIndex);
                    
                    if(!eleOffset) continue;

                    cols.push({
                        left: (eleOffset.left + 1) / sEvt.ratio,
                        top: eleOffset.top / sEvt.ratio,
                        width: eleOffset.width / sEvt.ratio,
                        height: eleOffset.height / sEvt.ratio,
                        index: i
                    });
                }
        
                sEvt.tableOperator.moveTo(rect, cols, rows, cellOffset, {
                    delegateForClick: function(e){
                        if(e.row || e.col || e.corner){
                            range = sEvt.selection.getRangeAt();
                            range.__position = sEvt.target.position;
    
                            var startOffset = ost.extractOffset(sEvt.target);
                            var endOffset = ost.extractOffset(sEvt.target);
    
                            if(e.row){
                                ost.mergeOffsetNext(startOffset, {
                                    tableRowIndex: e.index,
                                    tableColIndex: 0
                                });
                                ost.mergeOffsetNext(endOffset, {
                                    tableRowIndex: e.index,
                                    tableColIndex: table.getColCount() - 1
                                });
                            }else if(e.col){
                                ost.mergeOffsetNext(startOffset, {
                                    tableRowIndex: 0,
                                    tableColIndex: e.index
                                });

                                var endPageIndex = table.__boundRect.length - 1;
                                if(startOffset.pageIndex != endPageIndex){
                                    ost.updatePageIndexExceptLastNext(endOffset, endPageIndex);
                                }

                                ost.mergeOffsetNext(endOffset, {
                                    tableRowIndex: table.getRowCount() - 1,
                                    tableColIndex: e.index
                                });
                            }else if(e.corner){
                                ost.mergeOffsetNext(startOffset, {
                                    tableRowIndex: 0,
                                    tableColIndex: 0
                                });

                                var endPageIndex = table.__boundRect.length - 1;
                                if(startOffset.pageIndex != endPageIndex){
                                    ost.updatePageIndexExceptLastNext(endOffset, endPageIndex);
                                }

                                ost.mergeOffsetNext(endOffset, {
                                    tableRowIndex: table.getRowCount() - 1,
                                    tableColIndex: table.getColCount() - 1
                                });
                            }
    
                            range.startOffset = startOffset;
                            range.endOffset = endOffset;
    
                            startSelection.call(this);
                        }else if(e.colAdd || e.rowAdd){
                            var action = ACTIONS.pushModifyAction(type);
                            var index = e.index;

                            //添加列
                            if(e.colAdd){
                                var width = table.getColsWidth();
                                width = parseFloat((width / (table.getColCount() + 1)).toFixed(4));

                                var column = table.createTableColumn();

                                var rows = [];
                                for(var i = 0; i < table.getRowCount(); i++){
                                    var row = table.getRows(i);
                                    if(!rows[i]){
                                        rows[i] = [];
                                    }

                                    rows[i][index] = table.createTableCell();

                                    rows[i][index].children.push(document.createElement("sText"));
                                    rows[i][index].children.push(document.createElement("sParagraph"));
                                }

                                var recover = ()=>{
                                    table.insertColumnObj(index, column, {style:{width: width}});

                                    for(var i in rows){
                                        for(var j in rows[i]){
                                            table.getRows(i).insertCellObj(j, rows[i][j]);
                                        }
                                    }
                                };

                                var reverse = ()=>{
                                    table.getColumns().splice(index, 1);
                                    for(var i = 0; i < table.getRowCount(); i++){
                                        var row = table.getRows(i);
                                        row.getCells().splice(index, 1);
                                    }
                                };

                                action.setBeforeReverse(reverse);
                                action.setBeforeRecover(recover);

                                recover();

                                var col = null;
                                for(var i = 0; i < table.getColCount(); i++){
                                    col = table.getColumns(i);
                                    action.mutateTableCol(
                                        col, 
                                        {colIndex: i}, 
                                        {width: width}, 
                                        table
                                    );
                                }
                            }
                            //添加行
                            else if(e.rowAdd){
                                var row = table.createTableRow();
                                for(var i = 0; i < table.getColCount(); i++){
                                    var cell = row.insertCell(i);
                                    cell.children.push(document.createElement("sText"));
                                    cell.children.push(document.createElement("sParagraph"));
                                }

                                var recover = ()=>{
                                    table.insertRowObj(index, row);
                                }

                                var reverse = ()=>{
                                    table.getRows().splice(index, 1);
                                }

                                action.setBeforeReverse(reverse);
                                action.setBeforeRecover(recover);

                                recover();

                                action.mutateTableRow(
                                    row, 
                                    {rowIndex: index}, 
                                    null, 
                                    table
                                );
                            }

                            action.setOffset(offset);

                            render.reformat(
                                action.getElements(), offset, type, pageList, ssDict.sActionType.MODIFY);

                            var range = bindMethods.invoke("computePageRange", {
                                pageSize: pageList.getPageSize(), 
                                pageIndex: offset.pageIndex
                            });
                    
                            this.invalidate({range: range});
                            documentPageChange(sEvt, offset.pageIndex);

                            processEleProp.call(this, sEvt, render);
                        }
                    }
                });
            }
        }

        if(sEvt.eventType == "mousedown"){
            var outParam = {};
            var offset = ost.extractOffset(sEvt.target);
            var inRange = pageList.isInInputAreaRange(sEvt.target, type, outParam);
            var attributes = {};

            if(outParam.element){
                attributes = outParam.element.attributes;
                sEvt.belong = outParam;
            }

            //鼠标左键
            if(sEvt.nativeEvt.button != 0) return;

            if(inRange && attributes.dropdowntype){
                var key = outParam.element.__name;
                if(sEvt.dropdown.isActive() && sEvt.dropdown.getKey() == key){
                    sEvt.dropdown.blur();
                }else{
                    var rect = render.locateElementOffset(outParam.offset, outParam.element);
    
                    sEvt.dropdown.moveTo({
                        left: sEvt.baseOffset.left + rect.left / sEvt.ratio,
                        top: sEvt.baseOffset.top + 4 +
                            (sEvt.target.boundRect.top + sEvt.target.boundRect.height) / sEvt.ratio,
                        width: "auto",
                        height: "auto"
                    }, {
                        type: attributes.dropdowntype,
                        viewMode: attributes.viewMode,
                        search: true,
                        multiSelect: true,
                        key: key,
                        data: attributes.list ? attributes.list : [],
                        afterSelect: (item, option)=>{
                            let action = ACTIONS.pushReplaceAction();
                            let list = pageList.getInputAreaContent(outParam.offset, type);
                            
                            let paragraphIndex = null;
                            let itemOffset = null;
                            let it = null;

                            for(var i in list){
                                it = list[i];

                                action.addElement(it.ref, it.offset, type, {delete: true});
                                if(!paragraphIndex && it.ref._sType == "sText"){
                                    paragraphIndex = it.ref.__paragraphIndex;
                                    itemOffset = ost.extractOffset(it.offset);
                                }
                            }
                            
                            let text = document.createElement("sText");
                            text.__paragraphIndex = paragraphIndex;

                            let attrs = outParam.element.attributes;
                            if(attrs && attrs.valueFormat){
                                text.innerText = fmt.format(item.display, attrs.valueFormat, attributes.viewMode);
                            }else{
                                text.innerText = item.display;
                            }

                            if(text.innerText == null || text.innerText.length == 0){
                                text.placeholder = outParam.element.attributes &&
                                    outParam.element.attributes.backgroundtext
                                        ? outParam.element.attributes.backgroundtext
                                        : " ";
                            }

                            itemOffset.range = {start: 0, end: 0};
                            action.addElement(text, itemOffset, type, {mutateNew: true});
                            action.setOffset(offset);
                            
                            let result = render.reformat(
                                action.getElements(type), offset, type, pageList, ssDict.sActionType.REPLACE);
                            processRetypeResult.call(this, sEvt, render, result);
                        }
                    });
                }
            }else if(!sEvt.dropdown.isInRange({
                left: sEvt.offset.left / sEvt.ratio,
                top: sEvt.offset.top / sEvt.ratio
            })){
                sEvt.dropdown.blur();
            }

            // let locateInfo = render.locateElementOffset(offset, sEvt.target.ref);
            // sEvt.target = pageList.getPage(offset.pageIndex).search(locateInfo);
            // render.locate(sEvt);

            // setLastPmdEvt(sEvt);
        }

        if(sEvt.eventType == "mouseup"){
            let absoluteIndex = null;
            let next = ost.extractOffset(sEvt.target, true);
            absoluteIndex = next.contentIndex == null ? -1 : next.contentIndex;

            if(sEvt.target.ref._sType == "sText"){
                absoluteIndex = sEvt.target.prevTextLength + absoluteIndex;
            }

            let locateOffset = render.locateElementOffset2(sEvt.target.ref, absoluteIndex);
            sEvt.target = pageList.getPage(sEvt.target.pageIndex).search(locateOffset);
            sEvt.offset.left = locateOffset.left;
            sEvt.offset.top = locateOffset.top;
            render.locate(sEvt);
            
            setLastPmdEvt(sEvt);
        }
    }

    /**
     * 处理鼠标弹起触发的相关操作
     * @param {*} sEvt 
     * @param {*} render 
     */
    var processMouseUp = function(sEvt, render){
        sEvt = sEvt ? sEvt : lme;
        if(!sEvt) return;

        sEvt.target = sEvt.target 
            ? sEvt.target 
            : lme && lme.target;
        if(!sEvt.target) return;

        if(sEvt.target.ref._sType == "sLayer"){
            let layer = sEvt.target.ref;

            layer.dispatchEvent("mouseup", {
                callback: (e)=>{
                    e.element = layer;
                    events.dispatchEvent(e.eventName, e);
                }
            });

            let offset = ost.extractOffset(sEvt.target);
            let opt = {
                startPageIndex: offset.pageIndex,
                startRowIndex: offset.rowIndex
            };

            let subEl = null;

            if(layer.presentType == "checkbox"){
                subEl = layer.getSubElement("sCheckBox");
            }else if(layer.presentType == "radio"){
                subEl = layer.getSubElement("sRadio");
            }

            if(subEl && subEl.attributes){
                let script = subEl.attributes.script;
                if(script){
                    scriptFuncs.run(script);

                    let min = scriptFuncs.getMinIndex();

                    offset.minPageIndex = min.pageIndex;
                    offset.minRowIndex = min.rowIndex;
                }
            }

            if(sEvt.target.next){
                let next = ost.extractOffset(sEvt.target, true);
                opt.cellContentEdit = {
                    table: next.table,
                    tableRowIndex: next.tableRowIndex,
                    tableColIndex: next.tableColIndex
                }
                let tableRow = next.table.getRows(next.tableRowIndex);
                //如果当前编辑的这个单元格跨页
                //必须要从该单元格所在首页开始计算
                for(let i in tableRow.__boundRect){
                    if(opt.startPageIndex > parseInt(i)){
                        opt.startPageIndex = parseInt(i);
                    }
                    break;
                }
            }

            let result = render.reformat2(offset, sEvt.target.position, pageList, opt);

            let pageRange = bindMethods.invoke("getPageRange");
            for(let i in result.pageRange){
                if(pageRange.indexOf(result.pageRange[i]) < 0){
                    result.pageRange[i] = null;
                }
            }

            //必须包含当前页
            if(result.pageRange.indexOf(offset.pageIndex)){
                result.pageRange.push(offset.pageIndex);
            }

            this.invalidate({range: result.pageRange});
        }
    }

    /**
     * 获取表格元素布局成员的偏移量
     * @param {*} element 
     * @param {*} pageIndex
     */
    var getTableLayoutOffsetByPage = function(element, pageIndex){
        var offset = null;
        var rect = null;

        if(!element.__boundRect) return offset;

        for(var j in element.__boundRect[pageIndex]){
            if(!element.__boundRect[pageIndex]) return offset;

            rect = element.__boundRect[pageIndex][j];

            if(!rect || rect.height == 0) return offset;

            offset = {
                top: rect.top,
                left: rect.left,
                width: rect.width,
                height: rect.height
            }

            break;
        }
        
        return offset;
    }

    /**
     * 处理调整层元素大小的操作
     * @param {*} sEvt 
     * @param {*} start
     * @param {*} render
     */
    var processResize = function(sEvt, start, render){
        if(isDocReadOnlyOrForm()){
            return false;
        }

        if(sEvt.layerResize && sEvt.layerResize.isActive()){
            return processLayerResize(sEvt, start);
        }
        
        if(sEvt.cellResize){
            return processCellResize(sEvt, start, render);
        }
    }

    /**
     * 调整层元素的大小操作
     * @param {*} sEvt 
     * @param {*} start 
     * @returns 
     */
    var processLayerResize = function(sEvt, start){
        if(!sEvt.layerResize) return false;

        var lr = sEvt.layerResize;

        //调整层元素大小
        if(start && lr.isActive()){
            lr.reset();

            var direction = sEvt.nativeEvt.target.getAttribute("direction");
            if(!lr.isTrigger(direction)) return false;

            lr.__start = direction;

            var target = lme.target;
            var offset = ost.extractOffset(target);
            var rect = null;

            if(target.ref.style.position != "absolute"){
                var info = pageList.lookup(target.position, offset);
                rect = info.boundRect;
            }else{
                rect = {
                    left: target.ref.style.left,
                    top: target.ref.style.top,
                    width: target.ref.style.width,
                    height: target.ref.style.height
                };
            }
            
            lr.__startOffset = {
                left: rect.left,
                top: rect.top,
                width: rect.width,
                height: rect.height
            };

            return true;
        }else if(lr.__start){
            var width = lr.__startOffset.width;
            var height = lr.__startOffset.height;
            var ratio = lr.__startOffset.height / lr.__startOffset.width;

            if(lr.__start == "bottom-right"){
                var l = sEvt.offset.left - lr.__startOffset.left;
                var t = sEvt.offset.top - lr.__startOffset.top;
                
                if(Math.abs(l) >= Math.abs(t)){
                    width = Math.abs(l);
                    height = width * ratio;
                }else{
                    height = Math.abs(t);
                    width = height / ratio;
                }
            }else if(lr.__start == "bottom-left"){
                var l = sEvt.offset.left - lr.__startOffset.left;
                var t = sEvt.offset.top - lr.__startOffset.top;
                
                if(Math.abs(l) >= Math.abs(t)){
                    width -= l;
                    height = width * ratio;
                }else{
                    height = t;
                    width = height / ratio;
                }
            }else if(lr.__start == "bottom-center"){
                var t = sEvt.offset.top - lr.__startOffset.top;
                height = Math.abs(t);
            }else if(lr.__start == "top-right"){
                var l = sEvt.offset.left - lr.__startOffset.left;
                var t = sEvt.offset.top - lr.__startOffset.top;
                
                if(Math.abs(l) >= Math.abs(t)){
                    width = Math.abs(l);
                    height = width * ratio;
                }else{
                    height -= t;
                    width = height / ratio;
                }
            }else if(lr.__start == "top-left"){
                var l = sEvt.offset.left - lr.__startOffset.left;
                var t = sEvt.offset.top - lr.__startOffset.top;
                
                if(Math.abs(l) >= Math.abs(t)){
                    width -= l;
                    height = width * ratio;
                }else{
                    height -= t;
                    width = height / ratio;
                }
            }else if(lr.__start == "top-center"){
                var t = sEvt.offset.top - lr.__startOffset.top;
                height -= t;
            }else if(lr.__start == "middle-left"){
                var l = sEvt.offset.left - lr.__startOffset.left;
                width -= l;
            }else if(lr.__start == "middle-right"){
                var l = sEvt.offset.left - lr.__startOffset.left;
                width = Math.abs(l);
            }

            if(width <= height && width < 10){
                width = 10;
                height = 10 * ratio;
            }else if(height < width && height < 10){
                height = 10;
                width = 10 / ratio;
            }

            lr.__endOffset = {
                width: width / sEvt.ratio,
                height: height / sEvt.ratio
            };

            lr.resize(lr.__endOffset);

            return true;
        }

        //移动绝对定位层元素
        var range = sEvt.selection && sEvt.selection.getRangeAt();
        var collapsed = range && range.collapsed;

        if(collapsed){
            var ref = lme && lme.target.ref;
            if(ref && ref._sType == "sLayer" && ref.style.position == "absolute"){
                if(!lr.__relativeRect){
                    lr.__relativeRect = {
                        left: sEvt.offset.left - ref.style.left,
                        top: sEvt.offset.top - ref.style.top
                    }
                }else{
                    lr.__startMove = true;
                    lr.__moveRect = {
                        left: sEvt.offset.left - lr.__relativeRect.left,
                        top: sEvt.offset.top - lr.__relativeRect.top
                    };
                    lr.moveTo({
                        left: sEvt.baseOffset.left + lr.__moveRect.left / sEvt.ratio,
                        top: sEvt.baseOffset.top + lr.__moveRect.top / sEvt.ratio
                    });
                }
    
                return true;
            };
        }


        return false;
    }

    /**
     * 调整单元格大小操作
     * @param {*} sEvt 
     * @param {*} start 
     * @param {*} render
     */
    var processCellResize = function(sEvt, start, render){
        if(!sEvt.cellResize) return false;

        var cr = sEvt.cellResize;

        if(start){
            if(sEvt.target && sEvt.target.touchCellBorder){
                if(sEvt.target.touchCellBorder == "right"){
                    cr.__start = sEvt.target.touchCellBorder;
                }else if(sEvt.target.touchCellBorder == "bottom"){
                    cr.__start = sEvt.target.touchCellBorder;
                }

                cr.__event = sEvt;
                cr.__startOffset = {
                    left: sEvt.offset.left,
                    top: sEvt.offset.top
                };
    
                var offset = ost.extractCellOffset(sEvt.target, sEvt.target.touchTableRef);
                var next = ost.extractOffset(offset, true);
                var lookResult = pageList.lookup(sEvt.target.position, offset);

                var table = lookResult.tables ? lookResult.tables[0] : lookResult.ref;
                var spanCell = render.getSpanCell(table, next.tableRowIndex, next.tableColIndex);
                
                sEvt.cellResize.__startRowIndex = spanCell 
                    ? spanCell.getRowIndex() 
                    : next.tableRowIndex;
                sEvt.cellResize.__startColIndex = spanCell 
                    ? spanCell.getColIndex() 
                    : next.tableColIndex;

                sEvt.cellResize.__cell = spanCell ? spanCell.getRef() : lookResult.ref;
                sEvt.cellResize.__table = table;

                sEvt.cellResize.__rows = [];
                sEvt.cellResize.__cols = [];

                if(spanCell){
                    var endRowIndex = spanCell.getRowIndex() + spanCell.getRowspan() - 1;
                    for(var i = spanCell.getRowIndex(); i <= endRowIndex; i++){
                        sEvt.cellResize.__rows.push(table.getRows(i));
                    }
    
                    var endColIndex = spanCell.getColIndex() + spanCell.getColspan() - 1;
                    for(var i = spanCell.getColIndex(); i <= endColIndex; i++){
                        sEvt.cellResize.__cols.push(table.getColumns(i));
                    }
                }else{
                    sEvt.cellResize.__rows.push(table.getRows(next.tableRowIndex));
                    sEvt.cellResize.__cols.push(table.getColumns(next.tableColIndex));
                }

                // setLastPmdEvt(sEvt);
            }
        }

        if(cr.__start == "right"){
            cr.moveTo({
                left: sEvt.baseOffset.left + sEvt.offset.left / sEvt.ratio,
                top: sEvt.scrollOffset.top,
                width: 0,
                height: window.innerHeight
            });

            cr.__endOffset = {
                left: sEvt.offset.left,
                top: sEvt.offset.top
            };

            return true;
        }else if(cr.__start == "bottom"){
            cr.moveTo({
                left: sEvt.scrollOffset.left,
                top: sEvt.baseOffset.top + sEvt.offset.top / sEvt.ratio,
                width: window.innerWidth,
                height: 0
            }, true);

            cr.__endOffset = {
                left: sEvt.offset.left,
                top: sEvt.offset.top
            };

            return true;
        }

        return false;
    }

    /**
     * 开始调整大小
     * @param {*} sEvt 
     * @param {*} render 
     * @returns 
     */
    var startResize = function(sEvt, render){
        if(sEvt.layerResize && sEvt.layerResize.isActive()){
            return startLayerResize.call(this, sEvt, render);
        }
        
        if(sEvt.cellResize && sEvt.cellResize.isActive()){
            return startCellResize.call(this, sEvt, render);
        }
    }

    /**
     * 开始调整层元素大小
     * @param {*} sEvt 
     * @param {*} render 
     * @returns 
     */
    var startLayerResize = function(sEvt, render){
        var lr = sEvt.layerResize;

        //移动图标
        if(lr && lr.__startMove){
            var offset = ost.extractOffset(lme.target);
            var action = ACTIONS.pushModifyAction(type);

            action.mutateLayer(lme.target.ref, offset, { ...lr.__moveRect });

            this.invalidate({range: [offset.pageIndex]});

            lr.reset();
            return;
        }

        //调整大小
        if(!lr || !lr.__start || !lr.__endOffset) {
            if(lr) lr.reset();
            return;
        }

        var offset = ost.extractOffset(lme.target);
        var type = lme.target.position;
        var action = ACTIONS.pushModifyAction(type);

        action.mutateLayer(lme.target.ref, offset, {
            width: lr.__endOffset.width * sEvt.ratio,
            height: lr.__endOffset.height * sEvt.ratio,
        });

        if(lr.__endOffset.height != lr.__startOffset.height){
            offset.pageIndex -= offset.pageIndex > 1 ? 1 : 0;
        }

        if(lme.target.ref.style.position != "absolute"){

            var result = render.reformat(action.getElements(), 
            offset, type, pageList, ssDict.sActionType.MODIFY);

            var range = bindMethods.invoke("computePageRange", {
                pageSize: pageList.getPageSize(), 
                pageIndex: result.pageIndex
            });

            if(result.offset){
                ost.mergeOffset(lme.target, result.offset);
            }else{
                ost.mergeOffset(lme.target, ost.extractOffset(result));
            }

            var lookResult = pageList.lookup(type, ost.extractOffset(lme.target));
            lme.target.boundRect = lookResult.boundRect;

            this.invalidate({range: range});
            documentPageChange(lme, result.pageIndex);

            lme.eventType = sEvt.eventType;
            render.locate(lme, {relocate: relocate});

            if(result && result.needExpansion){
                processEleProp.call(this, lme, render);
            }
        }else{
            this.invalidate({range: [offset.pageIndex]});
        }

        lr.reset();
    }

    /**
     * 开始调整单元格大小
     * @param {*} sEvt 
     * @param {*} render 
     * @returns 
     */
    var startCellResize = function(sEvt, render){
        var cr = sEvt.cellResize;

        if(!cr || !cr.__start || !cr.__startOffset) {
            if(cr) cr.blur();
            return;
        }

        var len = 0;
        var minHeight = 0;
        var type = cr.__event.target.position;
        var action = ACTIONS.pushModifyAction(type);
        var offset = ost.extractOffset(cr.__event.target);

        //调整高度
        if(cr.__start == "bottom"){
            var endRowIndex = cr.__startRowIndex + cr.__cell.rowspan - 1;

            len = cr.__endOffset.top - cr.__startOffset.top;

            var height = 0;
            var totalHeight = 0;
            var tRow = null;
            var resizeRowIndex = 0;

            for(var i = cr.__startRowIndex; i <= endRowIndex; i++){
                tRow = cr.__table.getRows(i);

                for(var j in tRow.__boundRect){
                    for(var k in tRow.__boundRect[j]){
                        height = tRow.__boundRect[j][k].height;

                        if(height > 0){
                            resizeRowIndex = i;
                        }

                        totalHeight += height;
                    }
                }
            }

            len += totalHeight;
            
            var cell = cr.__table.getRows(resizeRowIndex).getCells(0);
            minHeight = parseFloat(cell.style.minHeight);

            len = len < minHeight
                ? minHeight
                : len;

            var mutateRow = null;

            if(cr.__cell.rowspan > 1){
                mutateRow = cr.__rows[resizeRowIndex - cr.__startRowIndex];
            }else{
                mutateRow = cr.__rows[cr.__rows.length - 1];
            }

            action.mutateTableRow(
                mutateRow, 
                offset, 
                { height: len },
                cr.__table
            );
        }else{
            var endColIndex = cr.__startColIndex + cr.__cell.colspan - 1;

            //调整宽度
            var mutateWidth = cr.__endOffset.left - cr.__startOffset.left;
            len = mutateWidth;

            var colWidth = 0;
            var width = 0;
            //计算合并单元格最后一列之前的所有列的宽度
            for(var i = cr.__startColIndex; i <= endColIndex; i++){
                if(i < endColIndex){
                    colWidth += cr.__table.getColumns(i).style.width;
                }
                width += cr.__table.getColumns(i).style.width;
            }

            len += width;

            var cell = null;
            var padding = null;
            var minWidth = 0;

            //计算单元格能改变的最大宽度
            for(var i = 0; i < cr.__table.getRows().length; i++){
                cell = cr.__table.getRows(i).getCells(endColIndex);
                padding = converter.parsePoM(cell.style.padding);
                minWidth = padding.left + padding.right;
                len = len < colWidth + minWidth 
                    ? colWidth + minWidth + minWidth + 10 
                    : len;
            } 

            action.mutateTableCol(
                cr.__cols[cr.__cols.length - 1], 
                offset, 
                { width: len - colWidth },
                cr.__table
            );

            //调整下一个列的宽度
            var nextColIndex = endColIndex + 1;
            var nextCol = cr.__table.getColumns(nextColIndex);
            if(nextCol){
                var nextColOffset = ost.mergeOffsetNext(
                    ost.extractOffset(offset), {
                        tableColIndex: nextColIndex
                    }
                );

                action.mutateTableCol(
                    nextCol, 
                    nextColOffset, 
                    { width: nextCol.style.width - mutateWidth},
                    cr.__table
                )
            }
        }

        render.reformat(action.getElements(), {...offset}, type, pageList, ssDict.sActionType.MODIFY);

        var range = bindMethods.invoke("computePageRange", {
            pageSize: pageList.getPageSize(), 
            pageIndex: offset.pageIndex
        });

        this.invalidate({range: range});

        documentPageChange(sEvt, offset.pageIndex);

        cr.blur();

        if(sEvt.target){
            processEleProp.call(this, sEvt, render);
        }else{
            lme.eventType = sEvt.eventType;
            processEleProp.call(this, lme, render);
        }
    }

    /**
     * 判断当前区域是否可编辑
     * @param {*} sEvt 
     * @param {*} edit 
     * @returns 
     */
    var canEdit = function(sEvt, edit){
        if(!sEvt || !sEvt.target) return false;

        //只读模式
        if(setting.docMode == ssDict.sDocMode.READ_ONLY){
            return false;
        }

        //表单模式下，只有输入域内容可修改
        if(setting.docMode == ssDict.sDocMode.FORM){
            let isEdit = sEvt.input || sEvt.delete || sEvt.enter || sEvt.paste || sEvt.cut || edit;
            if(isEdit){
                let outParam = {};
                let isInput = pageList.isInInputAreaRange(sEvt.target, sEvt.target.position, outParam);
                //非输入域或者输入域只读  
                if(!isInput || (outParam.element && outParam.element.attributes.readonly === true)){
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * 文档是否是只读或表单模式
     * @returns 
     */
    var isDocReadOnlyOrForm = function(){
        //只读、表单模式
        if(setting.docMode == ssDict.sDocMode.READ_ONLY ||
            setting.docMode == ssDict.sDocMode.FORM){
            return true;
        }
        return false;
    }

    /**
     * 处理对内容的增删改查
     * @param {*} sEvt 
     * @param {*} render 
     */
    var processCrud = function(sEvt, render){
        var result = null;

        updatePageIndexIfNotBody(sEvt, 1);

        if(!canEdit(sEvt)) return;

        if(sEvt.input){
            contentChange(sEvt);
            result = acceptInput.call(this, sEvt, render);
        }else if(sEvt.delete){
            contentChange(sEvt);
            if(sEvt.selection.getRangeAt().collapsed){
                result = deleteContent.call(this, sEvt, render);
            }else{
                result = deleteSelectContent.call(this, sEvt, render);
            }
        }else if(sEvt.enter){
            contentChange(sEvt);
            result = acceptEnter.call(this, sEvt, render);
        }else if(sEvt.selectAll){
            selectAll.call(this, sEvt);
        }else if(sEvt.copy){
            copy.call(this, sEvt, render);
        }else if(sEvt.cut){
            contentChange(sEvt);
            result = cut.call(this, sEvt, render);
        }else if(sEvt.paste){
            contentChange(sEvt);
            result = paste.call(this, sEvt, render);
        }else if(sEvt.undo){
            contentChange(sEvt);
            result = undo.call(this, sEvt, render);
        }else if(sEvt.redo){
            contentChange(sEvt);
            result = redo.call(this, sEvt, render);
        }

        setScroll(sEvt, 2);

        if(result && result.needExpansion){
            processEleProp.call(this, sEvt, render);
        }

        updatePageIndexIfNotBody(sEvt);
    }

    /**
     * 计算文本长度
     */
    var countText = function(){
        var textLength = countPageText(pageList);
        return textLength;
    }

    /**
     * 计算指定分页的文本长度
     * @param {*} pages 
     * @returns 
     */
    var countPageText = function(pages){
        var textLength = 0;

        pages.forEach((page, pageIndex)=>{
            page.forEach((row, rowIndex, type)=>{
                if(type != "body") return;
                row.forEach((element)=>{
                    if(element.style && element.style.display == "none") return;
                    if(element._sType == "sText"){
                        textLength += element.__texts[pageIndex][rowIndex].length;
                    }else if(element._sType == "sTable"){
                        for(let i = 0; i < element.getRowCount(); i++){
                            let row = element.getRows(i);
                            for(let j = 0; j < element.getColCount(); j++){
                                let cell = row.getCells(j);
                                if(!cell.__pageList) continue;
                                textLength += countPageText(cell.__pageList);
                            }
                        }
                    }
                })
            })
        });

        return textLength;
    }

    /**
     * 内容统计任务
     */
    var contentStatisticsTask = null;

    /**
     * 内容改变时触发
     * @param {*} sEvt
     */
    var contentChange = function(sEvt){
        finding.cache = null;
        finding.fragments = null;
        clearFindZone();

        bindMethods.invoke("contentChange");

        if(contentStatisticsTask){
            clearTimeout(contentStatisticsTask);
            contentStatisticsTask = null;
        }

        contentStatisticsTask = setTimeout(()=>{
            bindMethods.invoke("contentStatistics", {
                pageIndex: sEvt && sEvt.target ? sEvt.target.pageIndex : 1,
                pageSize: pageList.getPageSize(),
                textLength: countText()
            });
        }, 1000);
    }

    /**
     * 如果不是页体，则需要修改页码
     * 页眉和页脚各自只有一个实例
     * @param {*} sEvt 
     */
    var updatePageIndexIfNotBody = function(sEvt, pageIndex){
        if(sEvt.target && sEvt.target.position != "body"){
            if(pageIndex){
                sEvt.mutatePageIndex = parseInt(sEvt.handle);
                ost.updatePageWithRowIndex(sEvt.target, 1);
            }else if(sEvt.mutatePageIndex){
                ost.updatePageWithRowIndex(sEvt.target, sEvt.mutatePageIndex);
                delete sEvt.mutatePageIndex;
            }
        }
    }

    /**
     * 粘贴到文档内容的文本最大长度
     */
    const MAX_TEXT_LENGTH = 200;

    /**
     * 接收内容输入
     * @param {*} sEvt 
     * @param {*} render 
     * @returns 
     */
    var acceptInput = function(sEvt, render){
        if(!sEvt.target || !sEvt.target.ref){
            if(lme && lme.target && lme.target.ref){
                sEvt = lme;
            }else{
                return;
            }
        }

        var result = null;
        var type = sEvt.target.position;
        var pages = pageList;
        var range = sEvt.selection.getRangeAt();

        //当前内容处于被选择状态
        if(!range.collapsed){
            deleteSelectContent.call(this, sEvt, render);
            lme.data = sEvt.data;
            sEvt = lme;
        }

        var hasText = moveToNeighborText(sEvt, render);
        if(!hasText){
            sEvt = lme;
        }

        if(sEvt.id){
            bindSelector(sEvt.target.ref, {id: sEvt.id});
        }

        var offset = ost.extractOffset(sEvt.target);
        
        //文本内容过大，为了提高性能，需要拆分成多个元素
        if(sEvt.data.length > MAX_TEXT_LENGTH){
            var textList = splitLongText(sEvt.data, 
                sEvt.target.ref.style, sEvt.target.ref.__paragraphIndex)
                
            var action = ACTIONS.pushAddAction(type)
                .mutateText(sEvt.target.ref, offset);

            for(var i = 0; i < textList.length; i++){
                action.addText(textList[i], i == textList.length - 1, true);
            }

            offset.range = action.getRange();

            action.setOffset(offset);

            var elements = action.getElements();

            //对当前页进行排版
            result = render.reformat(
                elements,
                offset, 
                type,
                pages,
                ssDict.sActionType.INSERT
            );
        }else{
            if(offset.next){
                if(sEvt.data === "\t"){
                    moveCaretToCell.call(this, offset, type, render, sEvt.shift);
                    return;
                }
            }else{
                sEvt.data = sEvt.data === "\t" ? "   " : sEvt.data;
            }

            var opt = {};
            var next = null;

            if(offset.next){
                next = ost.extractOffset(offset, true);
                opt.cellContentEdit = {
                    table: next.table,
                    tableRowIndex: next.tableRowIndex,
                    tableColIndex: next.tableColIndex
                }
            }

            //没有可以接受文本输入的目标
            if(!hasText){
                var text = document.createElement("sText");
                text.__paragraphIndex = sEvt.target.ref.__paragraphIndex;
                text.innerText = sEvt.data;

                if(!next){
                    next = offset;
                }

                if(next.contentIndex == 0){
                    next.elementIndex += 1;
                }
                
                next.contentIndex = sEvt.data.length - 1;

                ost.mergeOffsetNext(offset, next);

                offset.range = {
                    start: next.contentIndex, 
                    end: next.contentIndex + 1
                };

                var action = ACTIONS.pushAddAction(type)
                    .add(text, offset);
                
                opt.notDeleteFirst = true;

                action.setOffset(offset, opt);

                var elements = action.getElements();

                //对当前页进行排版
                result = render.reformat(
                    elements,
                    offset, 
                    type,
                    pages,
                    ssDict.sActionType.INSERT,
                    opt
                );
            }else{
                var modifyAction = ACTIONS.pushModifyAction(type);
                var range = modifyAction
                    .mutateText(sEvt.target.ref, sEvt.data, offset)
                    .getRange();
                
                offset.range = range;
    
                modifyAction.setOffset(offset);

                //对当前页进行排版
                result = render.reformat(
                    modifyAction.getElements(), 
                    offset, 
                    type,
                    pages,
                    ssDict.sActionType.MODIFY,
                    opt
                );
            }
        }

        processRetypeResult.call(this, sEvt, render, result);

        return result;
    }

    /**
     * 分割长文本
     * @param {*} data 长文本
     * @param {*} style 文本样式
     * @param {*} paragraphIndex 段落序号
     * @returns 
     */
    var splitLongText = function(data, style, paragraphIndex){
        var length = Math.ceil(data.length / MAX_TEXT_LENGTH);
        var text = null;
        var textList = [];

        for(var i = 0; i < length; i++){
            text = document.createElement("sText");
            text.style = {...style};
            text.__paragraphIndex = paragraphIndex;
            text.innerText = data.substr(i * MAX_TEXT_LENGTH, MAX_TEXT_LENGTH);
            textList.push(text);
        }

        return textList;
    }

    /**
     * 将光标移动到下一个单元格
     * @param {*} offset 
     * @param {*} type
     * @param {*} render
     * @param {*} forward true向前移动 false往后移动
     */
    var moveCaretToCell = function(offset, type, render, forward){
        var cellOffset = ost.extractCellOffset(offset);
        var lookResult = pageList.lookup(type, cellOffset);
        var table = lookResult.tables[0];
        var next = ost.extractOffset(offset, true);
        var cell = lookResult.ref;

        if(forward){
            if(next.tableColIndex > 0){
                next.tableColIndex--;
            }else if(next.tableRowIndex > 0){
                next.tableRowIndex--;
                next.tableColIndex = table.getColumns().length - 1;
            }else{
            }

            var row = table.getRows(next.tableRowIndex);
            
            //跨页
            if(!row || !row.__boundRect[next.pageIndex] || 
                !table.getColumns(next.tableColIndex)){
                next.pageIndex -= 1;

                cellOffset.pageIndex = next.pageIndex;
                cellOffset.rowIndex = pageList
                    .getPage(cellOffset.pageIndex).getLastRow(type, true).getIndex();

                var pages = pageList;

                for(var n = cellOffset.next; n != null; n = n.next){
                    if(n.next){
                        n.pageIndex = next.pageIndex;

                        var shaloffset = ost.extractShallowOffset(n);
                        lookResult = pages.lookup(type, shaloffset);

                        n.rowIndex = lookResult.ref.__pageList
                            .getPage(next.pageIndex).getLastRow(type, true).getIndex();
                    }
                }
            }
        }else{
            if(next.tableColIndex + cell.colspan - 1 < table.getColumns().length - 1){
                next.tableColIndex += cell.colspan;
            }else if(next.tableRowIndex < table.getRows().length - 1){
                next.tableRowIndex++;
                next.tableColIndex = 0;
            }else{
            }

            var row = table.getRows(next.tableRowIndex);
            
            //跨页
            if(!row || !row.__boundRect[next.pageIndex] || 
                !table.getColumns(next.tableColIndex)){
                next.pageIndex += 1;
                ost.updatePageIndexExceptLastNext(cellOffset, next.pageIndex);
            }
        }

        ost.mergeOffsetNext(cellOffset, next);
        
        var lookResult = pageList.lookup(type, cellOffset);
        lookResult.left = lookResult.boundRect.left;
        lookResult.top = lookResult.boundRect.top;

        processRetypeResult.call(this, lme, render, lookResult);

        ost.mergeOffsetNext(lme.target, {
            tableRowIndex: next.tableRowIndex
        });

        setScroll(lme, 2);
    }

    /**
     * 绑定选择器
     * @param {*} element 元素
     * @param {*} opt {id:唯一编码, name:名称}
     */
    var bindSelector = function(element, opt){
        if(!opt) return;

        if(opt.id){
            element.id = opt.id;
        }

        if(opt.name){
            element.name = opt.name;
        }
    }

    /**
     * 接收回车键
     * @param {*} sEvt 
     * @param {*} render 
     */
    var acceptEnter = function(sEvt, render) {
        var pages = pageList;
        var result = null;

        var offset = ost.extractOffset(sEvt.target);
        var type = sEvt.target.position;

        var opt = null;
        var action = ACTIONS.pushAddAction(type);

        //软回车
        if(sEvt.shift){
            var breakline = document.createElement("sBreakline");
            if(sEvt.target.ref._sType == "sText"){
                var breaklineOffset = ost.plusElementIndex(ost.extractOffset(offset));
                action.divideTextAndInsertElement(
                    sEvt.target.ref, offset, breakline, breaklineOffset, {
                        leftTextEmptyCreate: true,
                        rightTextEmptyCreate: true
                    });
            }else{
                let text = document.createElement("sText");
                text.__paragraphIndex = sEvt.target.ref.__paragraphIndex;

                action.add(breakline, {...offset, 
                    elementIndex: offset.elementIndex + 1,
                    contentIndex: -1
                }).add(text, {...offset, 
                    rowIndex: offset.rowIndex + 1,
                    elementIndex: 0,
                    contentIndex: -1
                });

                offset.elementIndex += 1;
                opt = {notDeleteFirst: true};
            }
        }else{
            var eleOffset = ost.extractOffset(offset);
            var nType = type;

            if(offset.next){
                var prevNext = ost.trimLastNext(ost.extractOffset(offset));
                var lastNext = ost.extractOffset(offset, true);

                //表格在第一页第一行，且光标在第一个单元格内的第一行
                //则将光标移到第一行进行回车
                if(prevNext.pageIndex == 1 && 
                    prevNext.rowIndex == 1 && 
                    lastNext.rowIndex == 1 &&
                    lastNext.tableRowIndex == 0 &&
                    lastNext.tableColIndex == 0 &&
                    lastNext.contentIndex == -1){

                    //TODO
                    let row = pageList.getPage(prevNext.pageIndex).getRow(type, prevNext.rowIndex - 1);
                    let text = document.createElement("sText");
                    let paragraph = document.createElement("sParagraph");

                    row.getElementList().splice(0, 0, text, paragraph);

                    let result = render.reformat2(prevNext, type, pageList, {
                        startPageIndex: prevNext.pageIndex,
                        startRowIndex: prevNext.rowIndex
                    });
                    processRetypeResult.call(this, sEvt, render, result);

                    return result;
                }

                var cell = pageList.lookup(type, ost.extractCellOffset(offset));
                pages = cell.ref.__pageList;
                eleOffset = ost.extractOffset(offset, true);
                nType = "body";
            }

            var paragraph = document.createElement("sParagraph");

            if(sEvt.target.ref._sType == "sText"){
                var paragraphOffset = ost.plusElementIndex(ost.extractOffset(offset));
                action.divideTextAndInsertElement(
                    sEvt.target.ref, offset, paragraph, paragraphOffset, {
                        leftTextEmptyCreate: true,
                        rightTextEmptyCreate: true,
                        elementProp: {
                            __paragraphIndex: sEvt.target.ref.__paragraphIndex
                        }
                    }
                );
            }else{
                let text = document.createElement("sText");
                text.__paragraphIndex = sEvt.target.ref.__paragraphIndex;

                let next = ost.extractOffset(offset, true);
                let elementIndex = next.contentIndex > -1 
                    ? next.elementIndex + 1 
                    : next.elementIndex;

                action.add(paragraph, ost.updateNext({...offset}, { 
                    elementIndex: elementIndex,
                    contentIndex: -1
                })).add(text, ost.updateNext({...offset}, {
                    rowIndex: offset.rowIndex + 1,
                    elementIndex: 0,
                    contentIndex: -1
                }));

                ost.updateNext(offset, {elementIndex: elementIndex});
                opt = {notDeleteFirst: true};
            }

            //因为插入了一个段落，所以属于该段落的元素全部要更新段落序号
            updateParagraphIndex(
                pages, 
                eleOffset, 
                paragraph, 
                sEvt.target.ref.__paragraphIndex, 
                nType, 
                true,
                (element, props)=>{
                    if(element._sType != "sParagraph") {
                        action.hang(element, props.oldParagraphIndex);
                    }else{
                        //记录变异的段落元素
                        action.mutateParagraph(paragraph, null, props);
                    }
                }
            );
        }

        //让光标定位到该处
        action.getLastElement().offset.range = {
            start: -1,
            end: 0
        };

        if(offset.next){
            let next = ost.extractOffset(offset, true);
            opt = opt ? opt : {};
            opt.cellContentEdit = {
                table: next.table,
                tableRowIndex: next.tableRowIndex,
                tableColIndex: next.tableColIndex
            }
        }

        offset.range = action.getRange();

        action.setOffset(offset, opt);

        var elements = action.getElements();

        //对当前页进行排版
        result = render.reformat(
            elements,
            offset, 
            type,
            pageList,
            ssDict.sActionType.INSERT,
            opt
        );

        processRetypeResult.call(this, sEvt, render, result);

        return result;
    }

    /**
     * 插入图片
     * @param {*} img image对象
     * @param {*} size 图片尺寸
     */
    this.acceptImage = function(img, option){
        if(!canEdit(lme, true)) return;

        option = option ? option : {};

        var size = {
            width: option.width,
            height: option.height
        };

        var layer = document.createElement("sLayer");
        var image = document.createElement("sImage");

        layer.setPresentType(option.presentType 
            ? option.presentType 
            : ssDict.sPresentType.IMAGE
        );

        layer.attributes = option;
        layer.style.zIndex = option.zIndex ? option.zIndex : 101;

        layer.children.push(image);
        image.src = img;

        var type = lme.target.position;
        var offset = ost.extractOffset(lme.target);
        var next = ost.extractOffset(lme.target, true);
        var pages = null;

        if(offset.next){
            var cellOffset = ost.extractCellOffset(lme.target);
            var lookResult = pageList.lookup(type, cellOffset);
            pages = lookResult.ref.__pageList;
        }else{
            pages = pageList;
        }

        var rect = pages.getFirstPage().getBoundRect(type, true);
        layer.style.width = size.width > rect.width ? rect.width : size.width;
        layer.style.height = size.height > rect.height ? rect.height : size.height;

        layer.__paragraphIndex = lme.target.ref.__paragraphIndex;

        var action = ACTIONS.pushAddAction(type);

        if(lme.target.ref._sType == "sText"){
            action.mutateText(lme.target.ref, offset)
                .add(layer, {...offset, range: {
                    start: next.contentIndex, 
                    end: next.contentIndex + 1
                }}
            );
        }else{
            next.elementIndex += 1;
            ost.mergeOffsetNext(offset, next);

            offset.range = {
                start: next.contentIndex, 
                end: next.contentIndex + 1
            };

            action.add(layer, offset);
        }
        
        var len = lme.target.text ? lme.target.text.length : 0;
        if(next.contentIndex > -1 && next.contentIndex < len - 1){
            action.addText(document.createElement("sText"), true);
        }

        //重新排版
        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];

        var opt = {notDeleteFirst: true};

        action.setOffset(offset, opt);

        var result = render.reformat(
            action.getElements(), offset, type, pageList, ssDict.sActionType.INSERT, opt);

        processRetypeResult.call(this, lme, render, result);
    }

    /**
     * 如果当前元素不是文本元素，则移动到相邻的文本元素，
     * 如果不存在返回false 否则返回true
     * @param {*} sEvt 
     * @param {*} render
     */
    var moveToNeighborText = function(sEvt, render){
        var target = sEvt.target;
        var offset = ost.extractOffset(sEvt.target, true);

        //当前元素不是文本元素
        if(sEvt.target.ref._sType != "sText"){
            if(sEvt.target.ref._sType == "sInputEnd" && 
               sEvt.target.ref.__prevSibling._sType == "sInputBegin"){
                setLastPmdEvt(sEvt);
                return false;
            }
            
            if(offset.contentIndex == -1 && !sEvt.target.isFirst){
                sEvt.keyName = "ArrowLeft";
                render.locate(sEvt, {relocate: relocate});
            }else if(offset.contentIndex == 0 && !sEvt.target.isLast){
                sEvt.keyName = "ArrowRight";
                render.locate(sEvt, {relocate: relocate});
                sEvt.target.contentIndex = -1;
            }

            delete sEvt.keyName;

            if(sEvt.target.ref._sType != "sText"){
                sEvt.target = target;
                setLastPmdEvt(sEvt);
                return false;
            }

        }

        return true;
    }

    /**
     * 插入可编辑层
     * @param {*} option 
     */
    this.insertEditableLayer = function(option){
        if(!lme || !lme.target) return;
        if(!canEdit(lme, true)) return;

        option = option ? option : {};

        var layer = document.createElement("sLayer");
        layer.setPresentType(ssDict.sPresentType.EDITABLE);
        
        layer.style.width = option.width ? option.width : 400;
        layer.style.height = option.height ? option.height : 160;
        
        var table = document.createElement("sTable");

        table.insertColumn(null, {
            style: {
                width: layer.style.width
            }
        });

        var cell = table.insertRow().insertCell();
        
        cell.children.push(document.createElement("sText"));
        cell.children.push(document.createElement("sParagraph"));

        layer.children.push(table);

        insertPresentLayer.call(this, layer, option);
    }

    /**
     * 插入页码
     * @param {*} option 可选项 {id:"", name:"", style:{}}
     */
    this.insertPageNum = function(option){
        if(!lme || !lme.target) return;
        if(!canEdit(lme, true)) return;

        option = option ? option : {};

        //使用层元素和文本元素构建呈现类型为页码的元素
        var type = lme.target.position;
        var layer = document.createElement("sLayer");
        layer.setPresentType(ssDict.sPresentType.PAGE_NUMBER);
        
        var paragraph = document.createElement("sParagraph");
        paragraphIndex = pageList.getFirstPage().addParagraph(paragraph, type);
        paragraph.__paragraphIndex = paragraphIndex;
        paragraph.style.textAlign = "center";

        var text = document.createElement("sText");

        text.__paragraphIndex = paragraphIndex;
        text.variable = {
            name: "pageIndex",
            format: option.format 
                ? option.format 
                : "第{pageIndex}页"
        };
        text.style.fontSize = option.fontSize ? option.fontSize : 11;
        text.style.fontFamily = option.fontFamily ? option.fontFamily : "宋体";
        text.style.color = option.color ? option.color : "#000";
        
        layer.style.display = "inline-block";
        layer.style.width = option.width ? option.width : 100;
        layer.style.height = option.height ? option.height : 30;
        
        layer.children.push(text);
        layer.children.push(paragraph);

        insertPresentLayer.call(this, layer, option);
    }

    /**
     * 插入复选框
     * @param {*} option 可选项 {id:"", name:"", style:{}}
     */
    this.insertCheckBox = function(option){
        if(!lme || !lme.target) return;
        if(!canEdit(lme, true)) return;

        option = option ? option : {};

        //使用层元素、图像元素和文本元素构建呈现类型为复选框的元素
        var type = lme.target.position;
        var layer = document.createElement("sLayer");
        var checkbox = document.createElement("sCheckBox", {
            ...option
        });

        layer.setPresentType(ssDict.sPresentType.CHECKBOX);
        layer.children.push(checkbox);
        
        layer.style.display = "inline-block";
        layer.style.width = option.width ? option.width : checkbox.style.width;
        layer.style.height = option.height ? option.height : checkbox.style.height;

        insertPresentLayer.call(this, layer, option);
    }

    /**
     * 插入单选框
     * @param {*} option 可选项 {id:"", name:"", style:{}}
     */
    this.insertRadio = function(option){
        if(!lme || !lme.target) return;
        if(!canEdit(lme, true)) return;

        option = option ? option : {};

        //使用层元素、图像元素和文本元素构建呈现类型为单选框的元素
        var type = lme.target.position;
        var layer = document.createElement("sLayer");
        var radio = document.createElement("sRadio", {
            ...option
        });

        layer.setPresentType(ssDict.sPresentType.RADIO);
        layer.children.push(radio);
        
        layer.style.display = "inline-block";
        layer.style.width = option.width ? option.width : radio.style.width;
        layer.style.height = option.height ? option.height : radio.style.height;
        
        var reverse = null;
        var recover = null;

        if(option.name){
            reverse = ()=>{
                events.addEventListener("mouseup", {
                    name: option.name,
                    element: layer
                });
            };

            recover = ()=>{
                events.removeEventListener("mouseup", {
                    name: option.name,
                    element: layer
                });
            }

            reverse();
        }

        var action = insertPresentLayer.call(this, layer, option);

        //action.setBeforeReverse(reverse);
        //action.setBeforeRecover(recover);
    }

    /**
     * 插入横线
     * @param {*} option 
     */
    this.insertLine = function(option){
        if(!lme || !lme.target) return;
        if(!canEdit(lme, true)) return;

        option = option ? option : {};

        //使用层元素和文本元素构建呈现类型为页码的元素
        var type = lme.target.position;
        var page = pageList.getPage(lme.target.pageIndex);
        var layer = document.createElement("sLayer");
        layer.setPresentType(ssDict.sPresentType.LINE);

        layer.style.display = "inline-block";
        layer.style.lineWidth = option.lineWidth ? option.lineWidth : 1;
        layer.style.lineDash = option.lineDash ? option.lineDash : null;
        layer.style.color = option.color ? option.color : null;
        layer.style.width = option.width ? option.width : page.getBoundRect(type).width;
        layer.style.height = option.height ? option.height : 10;
        layer.__paragraphIndex = lme.target.__paragraphIndex;

        insertPresentLayer.call(this, layer, option);
    }

    /**
     * 插入水印
     * @param {*} option 
     */
    this.insertWatermark = function(option){
        pageList.setWatermark(option);

        let pageRange = bindMethods.invoke("getPageRange");
        this.invalidate({range: pageRange});
    }

    /**
     * 获取水印
     */
    this.getWatermark = function(){
        return pageList.getWatermark();
    }

    /**
     * 获取底纹
     */
    this.getTexture = function(){
        return pageList.getTexture();
    }

    /**
     * 插入底纹
     * @param {*} option 
     */
    this.insertTexture = function(option){
        if(!option) return;

        if(option.image && typeof(option.image) == "string"){
            let img = new Image();
            img.src = option.image;
            img.onload = ()=>{
                option.image = img;
                
                pageList.setTexture(option);
                let pageRange = bindMethods.invoke("getPageRange");
                this.invalidate({range: pageRange});
            };
        }else{
            pageList.setTexture(option);
            let pageRange = bindMethods.invoke("getPageRange");
            this.invalidate({range: pageRange});
        }
    }

    /**
     * 插入分页符
     * @param {*} option 
     */
    this.insertPageBreak = function(option){
        if(!lme || !lme.target) return;
        if(!canEdit(lme, true)) return;

        option = option ? option : {};

        //使用层元素和文本元素构建呈现类型为页码的元素
        var type = lme.target.position;
        var page = pageList.getPage(lme.target.pageIndex);
        var layer = document.createElement("sLayer");
        layer.setPresentType(ssDict.sPresentType.PAGE_BREAK);

        var text = document.createElement("sText");
        text.innerText = option.title ? option.title : "分页符";
        text.style.fontSize = 9;
        layer.children.push(text);

        layer.style.display = "block";
        layer.style.lineWidth = option.lineWidth ? option.lineWidth : 1;
        layer.style.width = option.width ? option.width : page.getBoundRect(type).width;
        layer.style.height = option.height ? option.height : 10;

        layer.__paragraphIndex = lme.target.__paragraphIndex;

        if(option.color){
            text.style.color = option.color;
            layer.style.color = option.color;
        }

        insertPresentLayer.call(this, layer, option);
    }

    /**
     * 插入具有特定呈现类型的层元素
     * @param {*} layer 层元素
     * @param {*} option 可选项
     */
    var insertPresentLayer = function(layer, option){
        //删除具体事件类型，避免因mousedown而使得layer呈现选中状态
        delete lme.eventType;

        var type = lme.target.position;
        var offset = ost.extractOffset(lme.target);
        var next = ost.extractOffset(lme.target, true);
        var pages = null;

        if(offset.next){
            var cellOffset = ost.extractCellOffset(lme.target);
            var lookResult = pageList.lookup(type, cellOffset);
            pages = lookResult.ref.__pageList;
        }else{
            pages = pageList;
        }

        var rect = pages.getFirstPage().getBoundRect(type, true);

        layer.style.width = layer.style.width > rect.width 
            ? rect.width : layer.style.width;
        layer.style.height = layer.style.height > rect.height 
            ? rect.height : layer.style.height;

        layer.__paragraphIndex = lme.target.ref.__paragraphIndex;

        var action = ACTIONS.pushAddAction(type);
        var opt = {notDeleteFirst: true};

        if(lme.target.ref._sType == "sText"){
            action.divideTextAndInsertElement(
                lme.target.ref, 
                offset, 
                layer, 
                null,
                {main: true}
            );
        }else{
            next.elementIndex += 1;
            ost.mergeOffsetNext(offset, next);

            offset.range = {
                start: next.contentIndex, 
                end: next.contentIndex + 1
            };

            action.add(layer, offset);
        }
        
        //重新排版
        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];

        action.setOffset(offset, opt);

        var result = render.reformat(
            action.getElements(), offset, type, pageList, ssDict.sActionType.INSERT, opt);

        processRetypeResult.call(this, lme, render, result);

        return action;
    }

    /**
     * 插入输入域
     * @param {*} option 
     * option.type：输入域类型，包含文本输入、下拉框等
     * option.dropdownType：下拉框类型，包含日历、列表等
     * option.viewMode：视图模式，包含跟下拉框类型相关，比如日历有日期、时间等模式
     */
    this.insertInputArea = function(option){
        if(!lme || !lme.target) return;
        if(!canEdit(lme, true)) return;

        option = option ? option : {};
        
        var counter = bindMethods.invoke("getCounter");
        if(!counter.inputArea){
            counter.inputArea = 0;
        }

        counter.inputArea++;

        var paragraphIndex = lme.target.ref.__paragraphIndex;

        var beginTag = document.createElement("sInputBegin");
        var endTag = document.createElement("sInputEnd");
        var text = document.createElement("sText");

        beginTag.__name = "input_area_" + counter.inputArea;
        endTag.__name = "input_area_" + counter.inputArea;

        beginTag.__endTag = endTag;
        endTag.__beginTag = beginTag;

        beginTag.__paragraphIndex = paragraphIndex;
        endTag.__paragraphIndex = paragraphIndex;
        text.__paragraphIndex = paragraphIndex;

        // beginTag.__placeholder = text;

        beginTag.attributes = option;
        endTag.attributes = option;

        //绑定监听器
        this.bindListener(beginTag);

        text.placeholderColor = "#ccc";
        text.placeholder = option.placeholder ? option.placeholder : "输入域";

        var groupElements = [beginTag, text, endTag];

        var type = lme.target.position;
        var offset = ost.extractOffset(lme.target);
        var next = ost.extractOffset(lme.target, true);
        var action = ACTIONS.pushAddAction(type);
        var opt = {notDeleteFirst: true};

        if(lme.target.ref._sType == "sText"){
            action.mutateText(lme.target.ref, offset);
            
            for(var i in groupElements){
                action.add(groupElements[i], {...offset, range: {
                    start: next.contentIndex, 
                    end: next.contentIndex + 1
                }});
            }
        }else{
            offset = ost.mergeOffsetNext(offset, {elementIndex: next.elementIndex + 1});

            var eleOffset = null;
            var elementIndex = next.elementIndex;

            for(var i in groupElements){
                eleOffset = ost.extractOffset(offset);

                ost.mergeOffsetNext(eleOffset, {elementIndex: ++elementIndex});

                eleOffset.range = {
                    start: next.contentIndex, 
                    end: next.contentIndex + 1
                };

                action.add(groupElements[i], eleOffset);
            }

        }

        var len = lme.target.text ? lme.target.text.length : 0;
        if(next.contentIndex > -1 && next.contentIndex < len - 1){
            action.addText(document.createElement("sText"), true);
        }
        
        //重新排版
        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];

        action.setOffset(offset, opt);

        var result = render.reformat(
            action.getElements(), offset, type, pageList, ssDict.sActionType.INSERT, opt);

        processRetypeResult.call(this, lme, render, result);

        return action;
    }

    /**
     * 设置数据源
     * @param {*} json 
     */
    this.setDataSource = function(json){
        let areas = [];

        let startPageIndex = null;
        let startRowIndex = null;
        let minPageIndex = null;
        let minRowIndex = null;
        let count = 0;

        for(let i in json){
            //输入域
            let elements = this.querySelectorAll(`[_sType='sInputBegin'][datasourcename='${i}']`);
            if(!elements || elements.length == 0) continue;

            count++;

            let el = null;
            for(let j in json[i]){
                for(let k in elements){
                    el = elements[k];

                    if(!el.ref.attributes) continue;
                    if(el.ref.attributes.datasourcefield != j){
                        continue;              
                    }

                    if(el.ref.__nextSibling && el.ref.__nextSibling._sType == "sText"){
                        el.ref.__nextSibling.innerText = json[i][j];
                    }    

                    if(areas.indexOf(el.position) < 0){
                        areas.push(el.position);
                    }

                    if(!startPageIndex){
                        startPageIndex = el.pageIndex;
                        startRowIndex = el.rowIndex;
                        minPageIndex = el.pageIndex;
                        minRowIndex = el.rowIndex;
                    }

                    if(startPageIndex > el.pageIndex){
                        startPageIndex = el.pageIndex;
                        startRowIndex = el.rowIndex;
                    }else if(startPageIndex == el.pageIndex && startRowIndex > el.rowIndex){
                        startRowIndex = el.rowIndex;
                    }

                    if(minPageIndex < el.pageIndex){
                        minPageIndex = el.pageIndex;
                        minRowIndex = el.rowIndex;
                    }else if(minPageIndex == el.pageIndex && minRowIndex < el.rowIndex){
                        minRowIndex = el.rowIndex;
                    }
                }
            }
        }

        if(count == 0) return;
        
        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];

        render.reformat2({
            minPageIndex: minPageIndex,
            minRowIndex: minRowIndex
        }, "all", pageList, {
            startPageIndex: startPageIndex,
            startRowIndex: startRowIndex
        });

        this.invalidate({range: pageRange});
    }

    /**
     * 给指定元素绑定监听器
     * @param {*} element 元素
     * @param {*} option 可选项
     */
    this.bindListener = function(element, option){
        if(element._sType == "sInputBegin"){
            element.addEventListener("visibleChange", (e)=>{
                let selector = fetchSelector(e.target);
                let els = pageList.querySelector(selector, {queryAll: true});

                els[0].contentIndex = 0;
                els[1].contentIndex = -1;

                let fragments = pageList.extractFragment(
                    ost.extractOffset(els[0]),
                    ost.extractOffset(els[1]),
                    els[0].position, {
                        containInvisible: true,
                        excludeTableCell: true
                    }
                );

                let hide = e.target.style.display == "none";
                let fragment = null;

                for(let i in fragments){
                    for(let j in fragments[i]){
                        fragment = fragments[i][j];
                        if(hide){
                            fragment.element.__display = fragment.element.style.display;
                            fragment.element.style.display = "none";
                        }else{
                            fragment.element.style.display = fragment.element.__display
                                ? fragment.element.__display
                                : e.target.style.display;
                        }
                    }
                }
            });
        }
    }

    /**
     * 抽取元素的选择器
     * @param {*} element 
     */
    var fetchSelector = function(element){
        let selector = null;

        if(element.__name){
            selector = "[__name='" + element.__name + "']";
        }else if(element.id){
            selector = "#" + element.id;
        }else if(element.name){
            selector = "[name='" + element.name + "']";
        }

        return selector;
    }

    /**
     * 插入表格
     * @param {*} option 
     */
    this.insertTable = function(option){
        if(!lme || !lme.target) return;
        if(!canEdit(lme, true)) return;

        var type = lme.target.position;
        var offset = ost.extractOffset(lme.target);

        var rowCount = parseInt(option.rowCount);
        var columnCount = parseInt(option.columnCount);

        var columnWidth = 0;
        if(offset.next){
            let next = ost.extractOffset(offset, true);
            let col = next.table.getColumns(next.tableColIndex);
            columnWidth = col.style.width / columnCount;
            columnWidth = columnWidth < 10 ? 10 : columnWidth;
        }else{
            let boundRect = pageList.getPage(offset.pageIndex).getBoundRect(type);
            columnWidth = boundRect.width / columnCount;
        }

        var table = document.createElement("sTable");

        for(var j = 0; j < columnCount; j++){
            table.insertColumn(null, {
                style: {
                    width: columnWidth
                }
            });
        }

        for(var i = 0; i < rowCount; i++){
            var row = table.insertRow();
            for(var j = 0; j < columnCount; j++){
                var cell = row.insertCell();
                cell.children.push(document.createElement("sText"));
                cell.children.push(document.createElement("sParagraph"));
            }
        }

        var action = ACTIONS.pushAddAction(type);
        var ref = lme.target.ref;

        var text = null;
        var lookResult = pageList.lookup(type, offset);
        var isNotEmpty = !lookResult.row.isVisualEmpty(true);

        //当前行不为空
        if(isNotEmpty){
            //光标位置在当前行首个元素的开头
            var isStart = lookResult.isFirst && lookResult.contentIndex == -1;

            if(isStart){
                if(ref._sType == "sText"){
                    action.mutateText(ref, offset);
                }else{
                    action.add(ref, offset);
                } 
            }else{
                var paragraph = document.createElement("sParagraph");
                updateParagraphIndex(pageList, offset, paragraph, 
                    ref.__paragraphIndex, type, true);
    
                if(ref._sType == "sText"){
                    action.mutateText(ref, offset);
                }else{
                    action.add(ref, offset);
                    ref.__paragraphIndex = paragraph.__paragraphIndex;
                }
    
                action.add(paragraph);
            }
        }
        
        action.add(table, {...offset, range: {
                start: -1, 
                end: -1
            }}, null, true);

        text = document.createElement("sText");
        text.__paragraphIndex = ref.__paragraphIndex;
        table.__paragraphIndex = ref.__paragraphIndex;

        if(ref._sType == "sText"){
            if(isNotEmpty){
                action.addText(text, true, true);
            }else{
                action.mutateText(ref, offset);
            }
        }
        
        //重新排版
        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];

        action.setOffset(offset);

        var result = render.reformat(action.getElements(), 
            offset, type, pageList, ssDict.sActionType.INSERT);

        processRetypeResult.call(this, lme, render, result);

    }

    /**
     * 对当前表格插入表格列
     * @param {*} option 
     */
    this.insertTableColumn = function(option){
        if(!lme || !lme.target || !lme.target.next) return;

        var type = lme.target.position;
        var offset = ost.extractOffset(lme.target);
        var next = ost.extractOffset(lme.target, true);
        var table = next.table;
        var index = option.direction == "left" 
            ? next.tableColIndex
            : next.tableColIndex + 1;

        var width = table.getColsWidth();
        width = parseFloat((width / (table.getColCount() + 1)).toFixed(4));

        var column = table.createTableColumn();

        var rows = [];
        var display = "";
        var spanCells = [];

        for(var i = 0; i < table.getRowCount(); i++){
            let row = table.getRows(i);
            let cell = row.getCells(index);
            
            if(cell.style.display == "none"){
                let spanCell = table.getSpanCell(i, index);
                let sIndex = spanCell.__colIndex + spanCell.colspan - 1;
                if(spanCells.indexOf(spanCell) < 0 && 
                   index > spanCell.__colIndex && 
                   index <= sIndex){
                    spanCell.colspan += 1;
                    display = "none";
                    spanCells.push(spanCell);
                }
            }else{
                display = "";
            }

            if(!rows[i]){
                rows[i] = [];
            }

            let newCell = table.createTableCell();

            newCell.children.push(document.createElement("sText"));
            newCell.children.push(document.createElement("sParagraph"));

            if(display){
                newCell.style.display = display;
            }

            rows[i][index] = newCell;
        }

        var recover = ()=>{
            table.insertColumnObj(index, column, {style:{width: width}});

            for(var i in rows){
                for(var j in rows[i]){
                    table.getRows(i).insertCellObj(j, rows[i][j]);
                }
            }
        };

        var reverse = ()=>{
            table.getColumns().splice(index, 1);
            for(var i = 0; i < table.getRowCount(); i++){
                var row = table.getRows(i);
                row.getCells().splice(index, 1);
            }
        };

        var action = ACTIONS.pushModifyAction(type);

        action.setBeforeReverse(reverse);
        action.setBeforeRecover(recover);

        recover();

        var col = null;
        for(var i = 0; i < table.getColCount(); i++){
            col = table.getColumns(i);
            action.mutateTableCol(
                col, 
                {colIndex: i}, 
                {width: width}, 
                table
            );
        }

        afterTableModified.call(this, action, offset, type);
    }

    /**
     * 对当前表格插入表格行
     * @param {*} option 
     */
    this.insertTableRow = function(option){
        if(!lme || !lme.target || !lme.target.next) return;

        var type = lme.target.position;
        var offset = ost.extractOffset(lme.target);
        var next = ost.extractOffset(lme.target, true);
        var table = next.table;
        var index = option.direction == "up" 
            ? next.tableRowIndex
            : next.tableRowIndex + 1;

        var row = table.createTableRow();
        if(index == 0 || index >= table.getRows().length - 1){
            for(var i = 0; i < table.getColCount(); i++){
                var cell = row.insertCell(i);
                cell.children.push(document.createElement("sText"));
                cell.children.push(document.createElement("sParagraph"));
            }
        }else{
            var curRow = table.getRows(index);
            var spanCells = [];
            var display = "";
            for(var i = 0; i < table.getColCount(); i++){
                let pCell = curRow.getCells(i);

                if(pCell.style.display == "none"){
                    let spanCell = table.getSpanCell(index, i);
                    let sIndex = spanCell.__rowIndex + spanCell.rowspan - 1;
                    if(spanCells.indexOf(spanCell) < 0 &&
                       index > spanCell.__rowIndex && 
                       index <= sIndex){
                        spanCell.rowspan += 1;
                        display = "none";
                        spanCells.push(spanCell);
                    }
                }else{
                    display = "";
                }

                let cell = row.insertCell(i);
                cell.children.push(document.createElement("sText"));
                cell.children.push(document.createElement("sParagraph"));

                if(display){
                    cell.style.display = display;
                }
            }                
        }

        var recover = ()=>{
            table.insertRowObj(index, row);
        }

        var reverse = ()=>{
            table.getRows().splice(index, 1);
        }

        var action = ACTIONS.pushModifyAction(type);
        
        action.setBeforeReverse(reverse);
        action.setBeforeRecover(recover);

        recover();

        action.mutateTableRow(
            row, 
            {rowIndex: index}, 
            null, 
            table
        );

        afterTableModified.call(this, action, offset, type);
    }

    /**
     * 对当前表格删除表格列
     * @param {*} option 
     */
    this.deleteTableColumn = function(option){
        if(!lme || !lme.target || !lme.target.next) return;

        var type = lme.target.position;
        var offset = ost.extractOffset(lme.target);
        var next = ost.extractOffset(lme.target, true);
        var table = next.table;
        var index = next.tableColIndex;

        var column = null;
        var cells = [];
        var recover = ()=>{
            //重新定义列宽
            column = table.getColumns().splice(index, 1)[0];

            let cols = table.getColumns();
            let width = column.style.width / cols.length;
            for(let i in cols){
                cols[i].style.width += width;
            }

            //计算合并单元格的属性
            let spanCells = [];
            let procSpanCell = (spanCell, colIndex)=>{
                if(colIndex == spanCell.__colIndex){
                    let cell = table.getRows(spanCell.__rowIndex).getCells(colIndex + 1);
                    cell.style.display = "";
                    cell.colspan = spanCell.colspan - 1;
                    cell.rowspan = spanCell.rowspan;
                }else if(colIndex > spanCell.__colIndex && 
                    colIndex <= spanCell.__colIndex + spanCell.colspan - 1){
                    spanCell.colspan -= 1;
                }
            };

            for(var i = 0; i < table.getRowCount(); i++){
                let cell = table.getRows(i).getCells(index);

                if(cell.style.display == "none"){
                    let spanCell = table.getSpanCell(i, index);
                    if(spanCell && spanCells.indexOf(spanCell) < 0 && spanCell.colspan > 1){
                        procSpanCell(spanCell, index);
                    }
                }else if(cell.colspan > 1){
                    procSpanCell(cell, index);
                }
            }       
            
            //缓存已删除单元格
            let rows = table.getRows();
            for(let i = 0; i < rows.length; i++){
                let cell = rows[i].getCells().splice(index, 1)[0];
                cells.push(cell);
            }
        }

        var reverse = ()=>{
            let cols = table.getColumns();
            let width = column.style.width / cols.length;
            for(let i in cols){
                cols[i].style.width -= width;
            }

            table.insertColumnObj(index, column);
            
            let rows = table.getRows();
            for(let i = 0; i < rows.length; i++){
                rows[i].getCells().splice(index, 0, cells[i]);
            }
        }

        var action = ACTIONS.pushModifyAction(type);
        
        action.setBeforeReverse(reverse);
        action.setBeforeRecover(recover);

        recover();

        action.mutateTableCol(
            column, 
            {colIndex: index}, 
            null,
            table
        );

        afterTableModified.call(this, action, offset, type);
    }

    /**
     * 对当前表格删除表格行
     * @param {*} option 
     */
    this.deleteTableRow = function(option){
        if(!lme || !lme.target || !lme.target.next) return;

        var type = lme.target.position;
        var offset = ost.extractOffset(lme.target);
        var next = ost.extractOffset(lme.target, true);
        var table = next.table;
        var index = next.tableRowIndex;

        var row = null;
        var recover = ()=>{
            let curRow = table.getRows(index);
            let spanCells = [];
            let procSpanCell = (spanCell, rowIndex)=>{
                if(rowIndex == spanCell.__rowIndex){
                    let cell = table.getRows(rowIndex + 1).getCells(spanCell.__colIndex);
                    cell.style.display = "";
                    cell.rowspan = spanCell.rowspan - 1;
                    cell.colspan = spanCell.colspan;
                }else if(rowIndex > spanCell.__rowIndex && 
                    rowIndex <= spanCell.__rowIndex + spanCell.rowspan - 1){
                    spanCell.rowspan -= 1;
                }
            };

            for(var i = 0; i < table.getColCount(); i++){
                let cell = curRow.getCells(i);

                if(cell.style.display == "none"){
                    let spanCell = table.getSpanCell(index, i);
                    if(spanCell && spanCells.indexOf(spanCell) < 0 && spanCell.rowspan > 1){
                        procSpanCell(spanCell, index);
                    }
                }else if(cell.rowspan > 1){
                    procSpanCell(cell, index);
                }
            }       

            row = table.getRows().splice(index, 1)[0];
        }

        var reverse = ()=>{
            table.insertRowObj(index, row);
        }

        var action = ACTIONS.pushModifyAction(type);
        
        action.setBeforeReverse(reverse);
        action.setBeforeRecover(recover);

        recover();

        action.mutateTableRow(
            row, 
            {rowIndex: index}, 
            null, 
            table
        );

        afterTableModified.call(this, action, offset, type);
    }

    /**
     * 表格修改之后排版
     * @param {*} action 
     * @param {*} offset 
     * @param {*} type 
     */
    var afterTableModified = function(action, offset, type){
        action.setOffset(offset);

        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];

        render.reformat(
            action.getElements(), offset, type, pageList, ssDict.sActionType.MODIFY);

        var range = bindMethods.invoke("computePageRange", {
            pageSize: pageList.getPageSize(), 
            pageIndex: offset.pageIndex
        });

        this.invalidate({range: range});
        documentPageChange(lme, offset.pageIndex);

        processEleProp.call(this, lme, render);
    }

    /**
     * 合并单元格
     */
    this.mergeCell = function(){
        var elementList = groupByElementForFragment(range, {containParagraph: true});

        var result = canMergeCell(elementList);
        if(!result) return;

        var type = range.__position;
        var action = ACTIONS.pushModifyAction(type);
        var spanCell = result.spanCell;
        var offset = spanCell.offset[0];
        var prev = ost.extractLastNextPrevOffset(offset);

        var oldChildren = [...spanCell.element.children];
        var span = {
            rowspan: spanCell.element.rowspan,
            colspan: spanCell.element.colspan
        };
        var recover = ()=>{
            spanCell.element.rowspan = result.rowspan;
            spanCell.element.colspan = result.colspan;

            let ch = spanCell.element.children;            
            let element = null;
            for(let i in elementList){
                el = elementList[i];
                if(el.element === spanCell.element) continue;
                for(let j in el.element.children){
                    element = el.element.children[j];

                    if(element._sType == "sText" && !element.innerText) continue;
                    if(element._sType == "sParagraph" && (
                        ch.length == 0 || ch[ch.length - 1]._sType == element._sType
                    )){
                        continue;
                    }

                    ch.push(element);
                }
            }
        }

        var reverse = ()=>{
            spanCell.element.children = [...oldChildren];
            spanCell.element.rowspan = span.rowspan;
            spanCell.element.colspan = span.colspan;
            
            for(let i in elementList){
                elementList[i].element.style.display = "";
            }
        }

        action.setBeforeReverse(reverse);
        action.setBeforeRecover(recover);

        recover();

        action.mutateTableCell(
            spanCell.element, 
            {
                ...offset,
                startPageIndex: prev.pageIndex,
                startRowIndex: prev.rowIndex
            },
            null
        );
        
        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];

        offset = ost.extractCellOffset(offset);

        render.reformat(action.getElements(), offset, type, pageList, ssDict.sActionType.MODIFY);

        pageRange = bindMethods.invoke("computePageRange", {
            pageSize: pageList.getPageSize(), 
            pageIndex: offset.pageIndex
        });

        this.invalidate({range: pageRange});
        documentPageChange(lme, offset.pageIndex);
    }

    /**
     * 获取当前单元格
     * @returns 
     */
    var getCurrentCell = function(){
        if(!lme || !lme.target || !lme.target.ref) return null;
        
        var next = lme.target.next;
        if(!next.table) return null;

        var cell = next.table.getRows(next.tableRowIndex).getCells(next.tableColIndex);
        if(cell.style.display == "none"){
            lme.target = pageList.getPage(next.pageIndex).search(lme.offset);
            next = ost.extractOffset(lme.target, true);
            cell = next.table.getRows(next.tableRowIndex).getCells(next.tableColIndex);
        }

        return cell;
    }

    /**
     * 拆分单元格
     */
    this.splitCell = function(option){
        let cell = getCurrentCell();
        if(!cell) return;

        var target = lme.target;
        var next = ost.extractOffset(target, true);
        if(!next.table) return;

        var type = target.position;
        var offset = ost.extractOffset(target);

        var action = ACTIONS.pushModifyAction(type);
        var column = next.table.getColumns(next.tableColIndex);

        var colcount = 1;
        var rowcount = 1;

        option = option ? option : {};

        if(option.columnCount){
            colcount = parseInt(option.columnCount);
            colcount = colcount < 1 ? 1 : colcount - 1;
        }

        if(option.rowCount){
            rowcount = parseInt(option.rowCount);
            rowcount = rowcount < 1 ? 1 : rowcount - 1;
        }

        if(colcount <= 0 && rowcount <= 0) return; 

        var width = column.style.width;
        var spanCells = [];

        var recover = ()=>{
            if(next.colspan > 1 || next.rowspan > 1){
                splitSpanCell(next, rowcount, colcount);
            }else{
                splitCell(next, rowcount, colcount, spanCells);
            }
        }

        var reverse = ()=>{
            if(next.colspan > 1 || next.rowspan > 1){
            }else{
                //恢复列的宽度
                column.style.width = width;

                //移除插入和行和列
                next.table.getRows().splice(next.tableRowIndex + 1, rowcount);
                next.table.getColumns().splice(next.tableColIndex + 1, colcount);

                //移除插入的单元格
                let row = null;
                let rows = next.table.getRows();
                for(let i = 0; i < rows.length; i++){
                    row = rows[i];
                    row.getCells().splice(next.tableColIndex + 1, colcount);
                }

                //调整合并单元格的属性
                for(let i in spanCells){
                    spanCells[i].cell.rowspan = spanCells[i].rowspan;
                    spanCells[i].cell.colspan = spanCells[i].colspan;
                }
            }
        }

        action.setBeforeReverse(reverse);
        action.setBeforeRecover(recover);
        action.setOffset(offset);
        action.setActType(ssDict.sActionType.EMPTY);

        recover();

        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];

        render.reformat2(offset, type, pageList, {
            startPageIndex: offset.pageIndex,
            startRowIndex: offset.rowIndex
        });

        pageRange = bindMethods.invoke("computePageRange", {
            pageSize: pageList.getPageSize(), 
            pageIndex: offset.pageIndex
        });

        this.invalidate({range: pageRange});
        documentPageChange(lme, offset.pageIndex);
    }

    /**
     * 拆分单个单元格
     * @param {*} next 偏移量
     * @param {*} rowcount 新增行数
     * @param {*} colcount 新增列数
     * @param {*} spanCells 合并单元格扩展行列数
     */
    var splitCell = function(next, rowcount, colcount, spanCells){
        let row = null;
        let cell = null;
        let index = 0;
        let rowIndexs = [next.tableRowIndex];
        let column = next.table.getColumns(next.tableColIndex);

        //处理当前列左右两侧存在的跨行合并单元格
        row = next.table.getRows(next.tableRowIndex);

        let cells = row.getCells();
        let lastSpanCell = null;
        for(let i = 0; i < cells.length; i++){
            cell = cells[i];
            if(cell.style.display == "none"){
                cell = next.table.getSpanCell(next.tableRowIndex, i);
            }

            if(cell.rowspan > 1 && cell !== lastSpanCell){
                spanCells.push({
                    cell: cell,
                    rowspan: cell.rowspan,
                    colspan: cell.colspan
                });
                cell.rowspan += rowcount;
                lastSpanCell = cell;
            }
        }

        //添加新行
        let colLen = next.table.getColCount();
        for(let i = 1; i <= rowcount; i++){
            index = next.tableRowIndex + i;
            row = next.table.insertRow(index);
            for(let j = 0; j < colLen; j++){
                cell = row.insertCell(j);

                cell.children.push(document.createElement("sText"));
                cell.children.push(document.createElement("sParagraph"));
            }
            rowIndexs.push(index);
        }

        //创建新列和单元格
        let newCol = null;
        let width = column.style.width / (colcount + 1);
        //改变当前列的宽度
        column.style.width = width;

        for(let i = 1; i <= colcount; i++){
            index = next.tableColIndex + i;

            newCol = next.table.createTableColumn();
            newCol.style.width = width;

            next.table.insertColumnObj(index, newCol);

            for(let j = 0; j < rowIndexs.length; j++){
                row = next.table.getRows(rowIndexs[j]);
                cell = row.insertCell(index);

                cell.children.push(document.createElement("sText"));
                cell.children.push(document.createElement("sParagraph"));
            }
        }

        //隐藏相关单元格
        let rows = next.table.getRows();
        for(let i = 0; i < rows.length; i++){
            if(rowIndexs.indexOf(i) > -1) continue;
            row = rows[i];

            cell = row.getCells(next.tableColIndex);
            if(cell.style.display == "none"){
                cell = next.table.getSpanCell(i, next.tableColIndex);
            }

            spanCells.push({
                cell: cell,
                rowspan: cell.rowspan,
                colspan: cell.colspan
            });

            cell.colspan += colcount;

            for(let i = 1; i <= colcount; i++){
                index = next.tableColIndex + i;

                cell = row.insertCell(index);
                cell.style.display = "none";
            }
        }
    }

    /**
     * 拆分合并单元格
     * @param {*} next 偏移量
     * @param {*} rowcount 新增行数
     * @param {*} colcount 新增列数
     */
    var splitSpanCell = function(next, rowcount, colcount){
        //需要改变的跨列数
        let colspans = [];
        //当前单元格的末列序号
        let endColIndex = next.tableColIndex + next.colspan - 1;
        //当前单元格列范围
        let range = [next.tableColIndex, endColIndex];
        //算出拆分后每个单元格的宽度
        let avgWidth = next.table.getColsWidth(range) / (colcount + 1);

        //是否需要拆分列
        let needSplitCol = next.colspan != colcount + 1;

        //拆分行范围
        let rowRange = {
            start: next.tableRowIndex,
            end: next.tableRowIndex + rowcount
        };

        if(next.rowspan > 1){
            let remain = next.rowspan % (rowcount + 1);
            if(remain > 0){
                throw "行数必须是" + next.rowspan + "的约数";
            }
            rowRange.start = next.tableRowIndex;
            rowRange.end = next.tableRowIndex + next.rowspan - 1;
            rowRange.rowspan = next.rowspan / (rowcount + 1);
        }else{
            //插入新行
            let colLen = next.table.getColCount();
            for(let i = rowRange.start + 1; i <= rowRange.end; i++){
                let row = next.table.insertRow(i);
                for(let j = 0; j < colLen; j++){
                    let cell = row.insertCell(j);
                    cell.children.push(document.createElement("sText"));
                    cell.children.push(document.createElement("sParagraph"));
                }
            }
        }

        //拆分列
        if(needSplitCol){
            let index = 0;
            let width = 0;
            let rowLen = next.table.getRowCount();
            let colspan = 0;
            let increatement = 0;

            for(let i = next.tableColIndex; i <= endColIndex + increatement; i++){
                let col = next.table.getColumns(i);
                
                colspan++;

                if(parseInt(avgWidth) < parseInt(width + col.style.width)){
                    let remainWidth = 0;

                    //平均宽度大于当前列宽度
                    if(avgWidth > width){
                        remainWidth = width + col.style.width;
                        colspans.push(colspan);
                        colspan = 1;
                    }
                    //平均宽度等于当前列宽度(小数位太多，忽略)
                    else if(parseInt(avgWidth) == parseInt(width)){
                        colspans.push(1);
                        colspan = 0;
                        width = 0;
                        continue;
                    }else{
                        remainWidth = width;
                        colspans.push(1);
                        colspan = 1;
                    }

                    index = i + 1;

                    let newCol = next.table.createTableColumn();

                    newCol.style.width = remainWidth - avgWidth;
                    next.table.insertColumnObj(index, newCol);

                    col.style.width = col.style.width - newCol.style.width;
                    width = newCol.style.width;

                    //对每一行对应列加一个单元格
                    for(let j = 0; j < rowLen; j++){
                        let row = next.table.getRows(j);
                        let cell = row.insertCell(index);

                        cell.children.push(document.createElement("sText"));
                        cell.children.push(document.createElement("sParagraph"));
                        cell.style.display = "none";

                        //其他行
                        if(j < rowRange.start || j > rowRange.end){
                            let cell = row.getCells(i);
                            if(cell.style.display == "none"){
                                cell = next.table.getSpanCell(j, i);
                            }
                            cell.colspan += 1;
                        }
                    }

                    //平均宽度大于新增列的宽度
                    if(avgWidth > newCol.style.width){
                        i++;
                    }
                    increatement++;
                }else{
                    width += col.style.width;
                }
            }

            if(colspan > 0){
                colspans.push(colspan);
            }
            endColIndex += increatement;
        }

        //重新设置单元格的跨列数(拆分单元格所在行)     
        for(j = rowRange.start; j <= rowRange.end; j++){
            let row = next.table.getRows(j);
            let m = 0, n = next.tableColIndex;

            for(let i = n; i <= endColIndex; i++){
                let cell = row.getCells(i);

                if(i == n){
                    cell.style.display = "";
                    cell.rowspan = 1;
                    cell.colspan = 1;

                    if(rowRange.rowspan){
                        cell.rowspan = rowRange.rowspan;
                    }

                    if(colspans.length > 0){
                        cell.colspan = colspans[m];
                        n += colspans[m++];
                    }
                }else if(i < n){
                    cell.style.display = "none";
                }else{
                    cell.style.display = "";

                    if(rowRange.rowspan){
                        cell.rowspan = rowRange.rowspan;
                    }
                }
            }
        }
    }

    /**
     * 设置单元格边框
     * @param {*} option 
     */
    this.setCellBorder = function(option){
        if(!option) return;

        let cell = getCurrentCell();
        if(!cell) return;

        var next = ost.extractOffset(lme.target, true);
        if(!next.table) return;

        var borderType = option.borderType;
        var range = lme.selection.getRangeAt();
        var pageRange = [];
        
        if(range.collapsed){
            let cell = next.table.getRows(next.tableRowIndex).getCells(next.tableColIndex);
            setCellBorderStyle(cell, borderType, option.style);
            getPageRangeFromCell(cell, pageRange);
        }else{
            var elementList = groupByElementForFragment(range);
            var el = null;
            for(let i in elementList){
                el = elementList[i];
                if(el.element._sType == "sTableCell"){
                    setCellBorderStyle(el.element, borderType, option.style);
                    getPageRangeFromCell(el.element, pageRange);
                }
            }
        }

        this.invalidate({range: pageRange});
    }

    /**
     * 获取单元格的页码范围
     * @param {*} cell 
     * @param {*} pageRange
     * @returns 
     */
    var getPageRangeFromCell = function(cell, pageRange){
        for(let i = cell.__boundRect.length - 1; i > 0; i--){
            if(pageRange.indexOf(i) > -1) continue;
            pageRange.push(i);
        }
        return pageRange;
    }

    /**
     * 边框样式类型
     */
    var borderStyleTypes = [
        "border", 
        "borderLeft", 
        "borderRight", 
        "borderTop", 
        "borderBottom"
    ];

    /**
     * 设置单元格边框样式
     * @param {*} cell 单元格
     * @param {*} borderType 边框类型
     * @param {*} style 边框样式
     */
    var setCellBorderStyle = function(cell, borderType, style){
        //未指定边框类型，则对所有边框样式类型设置样式
        if(!borderType){
            if(!style) return;

            for(let i in borderStyleTypes){
                if(cell.style[borderStyleTypes[i]] != "none"){
                    cell.style[borderStyleTypes[i]] = {
                        ...cell.style[borderStyleTypes[i]], 
                        ...style
                    };
                }
            }
            return;
        }

        //外框线
        if(borderType == "borderOutside"){
            for(let i in borderStyleTypes){
                cell.style[borderStyleTypes[i]] = {...style};
            }
            return;
        }

        //无框线
        if(borderType == "borderNone"){
            for(let i in borderStyleTypes){
                cell.style[borderStyleTypes[i]] = "none";
            }
            return;
        }
        
        //单个方向的边框(左、上、右、下)
        if(cell.style[borderType] == "none"){
            cell.style[borderType] = {...style};
        }else{
            cell.style[borderType] = "none";
        }
    }

    /**
     * 获取单元格内边距
     * @param {*} option 
     */
    this.getCellPadding = function(option){
        var cell = getCurrentCell();
        if(!cell) return null;

        return converter.parsePoM(cell.style.padding);
    }

    /**
     * 设置单元格内边距
     * @param {*} option 
     */
    this.setCellPadding = function(option){
        if(!option || !option.padding) return;

        var cell = getCurrentCell();
        if(!cell) return;

        var padding = converter.parsePoM(option.padding);

        if(cell.style.padding){
            cell.style.padding = {...converter.parsePoM(cell.style.padding), ...padding};
        }else{
            cell.style.padding = padding;
        }

        afterTableModified2.call(this);
    }

    /**
     * 设置表格列宽
     * @param {*} option 
     */
    this.setTableColumnWidth = function(option){
        if(!option || !option.width) return;

        let cell = getCurrentCell();
        if(!cell) return;

        var next = ost.extractOffset(lme.target, true);
        var column = next.table.getColumns(next.tableColIndex);

        var width = parseFloat(option.width);
        var minusWidth = parseFloat(column.style.width) - width;
        column.style.width = width;

        var nextColumn = next.table.getColumns(next.tableColIndex + 1);
        if(nextColumn){
            width = parseFloat(nextColumn.style.width);
            if(width + minusWidth > nextColumn.MIN_WIDTH){
                nextColumn.style.width = width + minusWidth;
            }else{
                nextColumn.style.width = 10;
            }
        }

        afterTableModified2.call(this);
    }

    /**
     * 设置表格行高
     * @param {*} option 
     */
    this.setTableRowHeight = function(option){
        if(!option || !option.height) return;

        let cell = getCurrentCell();
        if(!cell) return;

        var next = ost.extractOffset(lme.target, true);
        var row = next.table.getRows(next.tableRowIndex);
        row.style.height = parseFloat(option.height);

        afterTableModified2.call(this);
    }

    /**
     * 设置为表格头
     * @param {*} option 
     */
    this.setTableRowHead = function(option){
        if(!lme || !lme.target) return;

        var next = ost.extractOffset(lme.target, true);
        var table = next.table;
        var row = table.getRows(next.tableRowIndex);

        var rowRange = [next.tableRowIndex];

        var cell = null;
        var cells = row.getCells();
        var rowInd = null;

        //找出合并单元格的行范围
        for(let i in cells){
            cell = cells[i];
            if(cell.rowspan > 1){
                rowInd = next.tableRowIndex + cell.rowspan - 1;
                rowRange.push(rowInd);
            }else if(cell.style.display == "none"){
                let outParam = {};
                table.getSpanCell(next.tableRowIndex, i, outParam);
                rowRange.push(outParam.rowIndex);
            }
        }

        if(row.head){
            rowInd = next.tableRowIndex + 1;

            let nextRow = table.getRows(rowInd);
            if(nextRow.head){
                if(rowRange.indexOf(rowInd) < 0){
                    throw "表格行必须连续";
                }
            }
        }else{
            rowInd = next.tableRowIndex - 1;

            if(next.tableRowIndex > 0){
                let prevRow = table.getRows(rowInd);
                if(!prevRow.head){
                    if(rowRange.indexOf(rowInd) < 0){
                        throw "表格行必须连续";
                    }
                }
            }
        }

        let flg = !row.head;

        for(let i in rowRange){
            row = table.getRows(rowRange[i]);
            row.head = flg;
        }

        afterTableModified2.call(this);
    }

    /**
     * 表格修改后排版
     */
    var afterTableModified2 = function(){
        var offset = ost.extractOffset(lme.target);
        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];

        render.reformat2(offset, lme.target.position, pageList, {
            startPageIndex: offset.pageIndex,
            startRowIndex: offset.rowIndex
        });

        pageRange = bindMethods.invoke("computePageRange", {
            pageSize: pageList.getPageSize(), 
            pageIndex: offset.pageIndex
        });

        this.invalidate({range: pageRange});
    }

    /**
     * 设置选择区域
     * @param {*} range
     * @param {*} opt
     */
    this.setRange = function(range, opt){
        if(range){
            opt = opt ? opt : {};

            if(range.selector){
                var target = pageList.querySelector(
                    range.selector, {queryAll: opt.queryAll, contentIndex: range.start});

                if(!opt.queryAll){
                    var option = null;

                    if(range.collapsed){
                        option = {locateContentIndex: target.locateContentIndex};
                    }

                    var sEvt = bindMethods.invoke("createMouseEvent", target.pageIndex);
                    sEvt.target = target;
                    sEvt.offset = {};

                    var render = renderList[target.pageIndex];
                    render.locate(sEvt, option);
    
                    setLastPmdEvt(sEvt);
                }
            }
        }else if(opt){
            var type = opt.type ? opt.type : "body";

            //移动到页面开头或结尾
            if(opt.moveToEnd || opt.moveToStart){
                var offset = null;
                var option = null;

                if(opt.moveToEnd){
                    offset = getPageEndOffset(pageList, type);
                    option = {locateLast: true};
                }else{
                    offset = getPageStartOffset(pageList, type);
                    option = {locateContentIndex: -1};
                }

                locateByOffset(offset, type, pageList, option);
            }
        }
    }

    /**
     * 获取页面第一个元素偏移量
     * @param {*} pages 
     * @param {*} type
     * @param {*} opt 
     */
    var getPageStartOffset = function(pages, type, opt){
        var firstPage = pages.getFirstPage();
        return {
            pageIndex: firstPage.getIndex(),
            rowIndex: firstPage.getFirstRow(type).getIndex(),
            elementIndex: firstPage.getFirstRow(type).getFirstVisEleIndex()
        }
    }

    /**
     * 获取页面最后一个元素偏移量
     * @param {*} pages 
     * @param {*} type
     * @param {*} opt 
     */
    var getPageEndOffset = function(pages, type, opt){
        var lastPage = pages.getLastPage();
        return {
            pageIndex: lastPage.getIndex(),
            rowIndex: lastPage.getLastRow(type).getIndex(),
            elementIndex: lastPage.getLastRow(type).getLastVisEleIndex()
        }
    }

    /**
     * 根据偏移量移动光标
     * @param {*} offset 
     * @param {*} type 
     * @param {*} pages 
     * @param {*} opt
     */
    var locateByOffset = function(offset, type, pages, opt){
        var lookResult = pages.lookup(type, offset);
        var render = renderList[offset.pageIndex];

        var sEvt = bindMethods.invoke("createMouseEvent", offset.pageIndex);
        render.lookResultMergeToEvt(sEvt, lookResult);
        render.locate(sEvt, opt);

        setLastPmdEvt(sEvt);
    }

    /**
     * 获取当前元素
     */
    this.getCurrentElement = function(){
        return lme && lme.target && lme.target.ref;
    }

    /**
     * 查询元素
     * @param {*} selector 选择器
     */
    this.querySelector = function(selector){
        let result = pageList.querySelector(selector);
        return result;
    }

    /**
     * 选择所有符合选择器的元素
     * @param {*} selector 选择器
     */
    this.querySelectorAll = function(selector){
        let result = [];
        
        for(let i in areas){
            let els = pageList.querySelector(selector, {
                queryAll: true, 
                position: areas[i]
            });
            result = result.concat(els);
        }

        return result;
    }
    
    /**
     * 判断是否可以合并单元格
     * @param {*} elementList 
     * @returns 
     */
    var canMergeCell = function(elementList){
        var startRowIndex = 0;
        var startColIndex = 0;
        var endRowIndex = 0;
        var endColIndex = 0;

        var el = null;
        var next = null;
        var spanCell = null;
        var tStruct = []; 

        for(i = 0; i < elementList.length; i++){
            el = elementList[i];
            if(el.element._sType != "sTableCell") {
                return null;
            }

            next = ost.extractOffset(el.offset[0], true);

            if(!spanCell){
                spanCell = el;
                startRowIndex = next.tableRowIndex;
                startColIndex = next.tableColIndex;
            }
       
            if(endRowIndex < next.tableRowIndex + el.element.rowspan - 1){
                endRowIndex = next.tableRowIndex + el.element.rowspan - 1;
            }

            if(endColIndex < next.tableColIndex + el.element.colspan - 1){
                endColIndex = next.tableColIndex + el.element.colspan - 1;
            }

            for(var j = next.tableRowIndex; 
                j < next.tableRowIndex + el.element.rowspan; j++){
                
                if(!tStruct[j]){
                    tStruct[j] = [];
                }

                for(var k = next.tableColIndex; 
                    k < next.tableColIndex + el.element.colspan; k++){
                    tStruct[j][k] = true;
                }
            }
        }

        //判断是否满足合并单元格条件
        //所有行上选择的列数相同
        var prevColCount = -1;
        var colCount = 0;

        for(var i in tStruct){
            for(var j in tStruct[i]){
                colCount++;
            }

            if(prevColCount == -1){
                prevColCount = colCount;
                
            }else if(prevColCount != colCount){
                return false;
            }

            colCount = 0;
        }

        return {
            spanCell: spanCell,
            rowspan: endRowIndex - startRowIndex + 1,
            colspan: endColIndex - startColIndex + 1
        }
    }

    /**
     * 删除内容
     * @param {*} sEvt 
     * @param {*} render 
     * @returns 
     */
    var deleteContent = function(sEvt, render) {
        if(!sEvt.target || !sEvt.target.ref) return;

        var type = sEvt.target.position;
        var nType = sEvt.target.position;
        var rootOffset = ost.extractOffset(sEvt.target);
        var pages = pageList;

        if(rootOffset.next){
            var target = pageList.lookup(type, 
                ost.extractCellOffset(rootOffset));
            pages = target.ref.__pageList;
            nType = "body";
        }

        if(sEvt.target.ref.delete){
            moveCaret(sEvt, render, "ArrowLeft");
            return;
        }

        var offset = ost.extractOffset(rootOffset, true);

        // pages.setDiffRow(offset.rowIndex, offset.pageIndex, nType, {
        //     diff: diffUtil
        // });
        
        //文档起始位置
        if(offset.pageIndex == 1 && 
           offset.rowIndex == 1 && 
           offset.elementIndex == 0 && 
           offset.contentIndex < 0) {
            return;
        }

        var deleteAction = ACTIONS.pushDeleteAction(type);
        var mutateElement = sEvt.target.ref;

        //当前光标所在元素
        if(mutateElement._sType == "sText"){
            deleteAction.mutateText(mutateElement, rootOffset);
        }else if(mutateElement._sType == "sInputBegin" || mutateElement._sType == "sInputEnd"){
            moveCaret(sEvt, render, "ArrowLeft");
        }else{
            if(offset.contentIndex == -1){
                deleteAction.add(mutateElement, {
                    ...rootOffset, 
                    range: {start: -1, end: -1}
                });
            }else{
                deleteAction.deleteLayer(mutateElement, {
                    ...rootOffset, 
                    range: {start: -1, end: 0}
                });
            }
        }

        //判断边界情况：当前是否行开头，上一行末尾是否段落、换行
        //在一行的开头
        if(sEvt.target.isFirst && offset.contentIndex == -1){
            var row = null;
            var pOffset = null;

            if(offset.rowIndex > 1){
                pOffset = {...offset, rowIndex: offset.rowIndex - 2};
                row = pages.getPage(pOffset.pageIndex).getRow(nType, pOffset.rowIndex);
            }else{
                if(offset.pageIndex > 1){
                    pOffset = {...offset, pageIndex: offset.pageIndex - 1};
                    row = pages.getPage(pOffset.pageIndex).getLastRow(nType, true);
                }
            }

            var elementList = row.getElementList();
            var isEndWithParagraph = row.isEndWithParagraph();
            var isEndWithBreakline = row.isEndWithBreakline();

            //如果当前元素前一个元素是段落或是换行符
            if(isEndWithParagraph || isEndWithBreakline){
                //是段落
                if(isEndWithParagraph){
                    //获取段落元素
                    var paragraph = elementList[elementList.length - 1];
                    var paraOffset = ost.extractOffset(rootOffset);

                    //设置偏移量
                    ost.mergeOffsetNext(paraOffset, {
                        pageIndex: row.getPageIndex(),
                        rowIndex: row.getIndex(),
                        elementIndex: elementList.length - 1
                    });

                    //将上一行段落元素插入到动作列表开头
                    deleteAction.deleteParagraph(paragraph, paraOffset, false, {prepend: true});
    
                    //将当前行所在段落元素样式设置为变异(删除)段落的元素样式
                    var info = pages.getNextParagraphInfo({
                        pageIndex: offset.pageIndex,
                        rowIndex: offset.rowIndex
                    }, nType);

                    info.offset = ost.mergeOffsetNext(ost.extractOffset(rootOffset), info.offset);
    
                    //重新排版最小截止页和行
                    if(!offset.minPageIndex || offset.minPageIndex < info.offset.pageIndex){
                        offset.minPageIndex = info.offset.pageIndex;
                    }

                    if(!offset.minRowIndex || offset.minRowIndex < info.offset.rowIndex){
                        offset.minRowIndex = info.offset.rowIndex;
                    }
    
                    var pIndex = offset.pageIndex;
                    var rIndex = offset.rowIndex - 1;
    
                    if(offset.rowIndex == 1 && offset.pageIndex > 1){
                        pIndex = offset.pageIndex - 1;
                        rIndex = pages.getPage(pIndex).getLastRow(type, true).getIndex();
                    }
    
                    //更新当前光标所在段落以及段落所在元素的段落序号
                    updateParagraphIndex(
                        pages,
                        {
                            pageIndex: pIndex,
                            rowIndex: rIndex,
                            elementIndex: null
                        }, 
                        info.ref, 
                        paragraph.__paragraphIndex, 
                        nType,
                        false,
                        (element, props)=>{
                            if(element._sType != "sParagraph"){
                                //更新段落内所有元素段落序号
                                deleteAction.hang(element, props.oldParagraphIndex);
                            }else{
                                //记录变异的段落元素
                                deleteAction.mutateParagraph(element, info.offset, props);
                            }
                        }
                    );
                }else if(isEndWithBreakline){
                    var breakline = elementList[elementList.length - 1];
                    var breakOffset = ost.extractOffset(rootOffset);

                    ost.mergeOffsetNext(breakOffset, {
                        pageIndex: row.getPageIndex(),
                        rowIndex: row.getIndex(),
                        elementIndex: elementList.length - 1
                    });

                    deleteAction.deleteBreakline(breakline, breakOffset);
                }
                
                //向左移动光标,指向上一个内容
                moveCaret(sEvt, render, "ArrowLeft");

                //移动后的当前元素不是变异元素，则加入到删除动作栈表中(此处加入是为了能和前面的元素连接起来)
                if(mutateElement != sEvt.target.ref){
                    var r = pages.getPage(sEvt.target.pageIndex).getRow(type, sEvt.target.rowIndex - 1);
                    deleteAction.add(
                        sEvt.target.ref, 
                        ost.extractOffset(sEvt.target), 
                        r && !r.isVisualEmpty(true), 
                        {prepend: true}
                    );
                }
            }else if(elementList[elementList.length - 1]._sType == "sTable"){
                //如果是表格，则将表格全选
                var table = elementList[elementList.length - 1];
                var newOffset = ost.extractOffset(rootOffset);
                var tableRange = getTableRange(table, newOffset);
                
                range = sEvt.selection.getRangeAt();
                
                range.__position = sEvt.target.position;
                range.startOffset = tableRange.startOffset;
                range.endOffset = tableRange.endOffset;

                startSelection.call(this);

                return;
            }else{
                //向左移动光标,指向上一个内容
                moveCaret(sEvt, render, "ArrowLeft", true);
                
                //移动后的当前元素不是变异元素，则加入到删除动作栈表中
                if(sEvt.target.ref._sType == "sText" && mutateElement != sEvt.target.ref){
                    deleteAction.mutateText(sEvt.target.ref, ost.extractOffset(sEvt.target));
                }else if(sEvt.target.ref._sType == "sLayer"){
                    deleteAction.add(sEvt.target.ref, ost.extractOffset(sEvt.target));
                }
            }

            if(offset.rowIndex - 1 <= 0){
                if(offset.pageIndex - 1 > 0){
                    offset.pageIndex -= 1;
                    offset.rowIndex = pages.getPage(offset.pageIndex).getLastRow(nType, true).getIndex();
                }
            }else{
                offset.rowIndex -= 1;
            }
        }
        //即将到达元素在当前行的起始位置
        else if(offset.contentIndex == 0){
            if(!sEvt.target.isFirst){
                // moveCaret(sEvt, render, "ArrowLeft");

                deleteAction.add(sEvt.target.ref, ost.extractOffset(sEvt.target));
            }else{
                var direction = "ArrowRight";
                var notSkipEnd = false;

                if(sEvt.target.ref._sType == "sText"){
                    if(sEvt.target.isLast ||
                        sEvt.target.contentIndex < sEvt.target.text.length - 1){
                        direction = null;
                    }
                }else if(sEvt.target.isLast){
                    ost.updateContentIndexForNext(sEvt.target);
                    direction = "ArrowLeft";
                    notSkipEnd = true;
                }

                if(direction){
                    moveCaret(sEvt, render, direction, notSkipEnd);

                    var newOffset = ost.extractOffset(sEvt.target);
                    var contentIndex = newOffset.contentIndex

                    if(direction == "ArrowRight"){
                        contentIndex = newOffset.contentIndex > 0 
                            ? newOffset.contentIndex - 1
                            : -1;
                    }
                        
                    newOffset.range = {
                        start: contentIndex,
                        end: contentIndex
                    };
    
                    var isEmpty = false;

                    if(sEvt.target.ref._sType == "sText"){
                        isEmpty = sEvt.target.ref.innerText == "" ||
                            sEvt.target.ref.innerText == null;
                    }

                    deleteAction.add(sEvt.target.ref, newOffset, isEmpty);
                }
            }
        }

        delete sEvt.keyName;

        ost.mergeOffsetNext(rootOffset, offset);

        deleteAction.setOffset(rootOffset);

        let opt = null;

        if(rootOffset.next){
            opt = {
                cellContentEdit: {
                    table: rootOffset.next.table,
                    tableRowIndex: offset.tableRowIndex,
                    tableColIndex: offset.tableColIndex
                }
            };
        }

        var elements = deleteAction.getElements();

        //对当前页进行排版
        var result = render.reformat(
            elements,
            rootOffset, 
            type,
            pageList,
            ssDict.sActionType.DELETE,
            opt
        );

        processRetypeResult.call(this, sEvt, render, result);

        return result;
    }

    /**
     * 获取表格元素的起始和结束偏移量
     * @param {*} table 
     * @param {*} offset
     */
    var getTableRange = function(table, offset){
        var rect = table.__boundRect;

        var startOffset = { contentIndex: -1 };
        var endOffset = { contentIndex: 0 };

        for(var i in rect){
            startOffset.pageIndex = parseInt(i);
            for(var j in rect[i]){
                startOffset.rowIndex = parseInt(j);
                break;
            }
            break;
        }

        endOffset.pageIndex = rect.length - 1;
        endOffset.rowIndex = rect[rect.length - 1].length - 1;

        var range = {
            startOffset: null,
            endOffset: null
        };

        //TODO 这里处理表格嵌套表格的情况
        if(startOffset.pageIndex != endOffset.pageIndex){

        }

        range.startOffset = ost.extractOffset(offset);
        ost.mergeOffsetNext(range.startOffset, startOffset);

        range.endOffset = ost.extractOffset(offset);
        ost.mergeOffsetNext(range.endOffset, endOffset);

        return range;
    }

    /**
     * 删除选择的内容
     * @param {*} sEvt 
     * @param {*} render 
     * @param {*} opt
     */
    var deleteSelectContent = function(sEvt, render, opt) {
        var range = sEvt.selection.getRangeAt();
        var elementList = groupByElementForFragment(range, {containParagraph: true});
        var type = range.__position;

        var deleteAction = ACTIONS.pushDeleteAction(type);
        deleteAction.setSelectionRange(range, true);

        var updateParagraph = {
            start: null,
            end: null
        };

        var pages = pageList;
        var deleteTable = null;
        var deleteTables = [];
        var el = null;
        var opt = {inTextEmptyCreate: true};

        elementList = filterElementForDelete(elementList);

        for(var i = 0; i < elementList.length; i++){
            el = elementList[i];
            
            if(el.element._sType == "sText"){
                opt.start = i == 0;
                opt.end = i == elementList.length - 1;
                deleteAction.deleteText(el.element, el.offset, null, opt);
            }else if(el.element._sType == "sLayer"){
                deleteAction.deleteLayer(el.element, el.offset[0], null, opt);
            }else if(el.element._sType == "sBreakline"){
                deleteAction.deleteBreakline(el.element, el.offset[0], null, opt);
            }else if(el.element._sType == "sParagraph"){
                deleteAction.deleteParagraph(el.element, el.offset[0], null, opt);

                if(!updateParagraph.start){
                    updateParagraph.start = {...el};
                }else{
                    updateParagraph.end = {...el};
                }
            }else if(el.element._sType == "sTableCell"){
                if(!deleteTable || deleteTable.ref != el.table){
                    deleteTable = {
                        ref: el.table,
                        offset: el.offset[0],
                        startOffset: {
                            tableRowIndex: el.offset[0].next.tableRowIndex,
                            tableColIndex: el.offset[0].next.tableColIndex,
                            pageIndex: el.offset[0].pageIndex,
                            rowIndex: el.offset[0].rowIndex
                        },
                        endOffset: null
                    };

                    deleteTables.push(deleteTable);
                }

                deleteTable.endOffset = {
                    tableRowIndex: el.offset[0].next.tableRowIndex,
                    tableColIndex: el.offset[0].next.tableColIndex,
                    pageIndex: el.offset[0].pageIndex,
                    rowIndex: el.offset[0].rowIndex
                };
            }else if(el.element._sType == "sInputBegin"){
                deleteAction.deleteInputArea(el.element, el.offset[0], null, opt);
            }else if(el.element._sType == "sInputEnd"){
                deleteAction.deleteInputArea(el.element, el.offset[0], null, opt);
            }
        }

        //判断表格是否需要删除
        if(deleteTables.length > 0){
            for(var i in deleteTables){
                deleteTable = deleteTables[i];
                if(deleteTable.startOffset.tableRowIndex == 0 && 
                    deleteTable.startOffset.tableColIndex == 0 &&
                    deleteTable.endOffset.tableRowIndex == deleteTable.ref.getRows().length - 1 &&
                    deleteTable.endOffset.tableColIndex == deleteTable.ref.getColumns().length - 1){

                    deleteAction.deleteTable(deleteTable.ref, {...deleteTable.offset, ...{
                        startPageIndex: deleteTable.startOffset.pageIndex,
                        startRowIndex: deleteTable.startOffset.rowIndex,
                        endPageIndex: deleteTable.endOffset.pageIndex,
                        endRowIndex: deleteTable.endOffset.rowIndex
                    }});
                }
            }
        }

        //检查需要保留的元素
        keepElement(elementList[0], elementList[elementList.length - 1], type, deleteAction);

        //更新段落信息
        checkWithUpdateParagraph(updateParagraph, sEvt.target.position);
        
        var pageRange = bindMethods.invoke("getPageRange");

        if(!render){
            render = renderList[pageRange[0]];
        }

        //位置不能变
        var offset = {...range.startOffset};
        var elements = deleteAction.getElements();

        if(elements.length == 0){
            return;
        }

        deleteAction.setOffset(offset);
        
        var result = render.reformat(elements, 
            offset, type, pageList, ssDict.sActionType.DELETE);

        range.reset();

        for(var i in pageRange){
            render = renderList[pageRange[i]]
            render.getPainter().clearSelection();
        }

        el = elementList[0];

        if(pageRange.indexOf(el.offset[0].pageIndex) < 0){
            pageRange.push(el.offset[0].pageIndex);
        }

        processRetypeResult.call(this, sEvt, render, result);

        return result;
    }

    /**
     * 过滤不满足删除条件的元素
     * @param {*} elementList 
     * @returns 
     */
    var filterElementForDelete = function(elementList){
        var elements = [];
        var el = null;
        var lastBeginInd = -1;
        var lastEndInd = -1;
        var beginInd = -1;

        for(var i = 0; i < elementList.length; i++){
            el = elementList[i];
            if(el.element._sType == "sInputBegin" ){
                lastBeginInd = i;
                beginInd = elements.length;
            }else if(el.element._sType == "sInputEnd"){
                lastEndInd = i;
                if(lastBeginInd < 0){
                    continue;
                }
            }
            elements.push(el);
        }

        //输入域只有开始，没有结束标签
        if(lastBeginInd > -1 && lastEndInd < lastBeginInd){
            elements.splice(beginInd, 1);
        }

        return elements;
    }

    /**
     * 检查并更新段落信息
     * @param {*} updateParagraph 
     * @param {*} type
     */
    var checkWithUpdateParagraph = function(updateParagraph, type){
        if(!updateParagraph.start) return;

        var offset = updateParagraph.start.offset[0];
        var startOffset = ost.extractOffset(offset, true);
        var endOffset = null;

        var delFlg = true;

        //段落是选择的唯一元素
        if(updateParagraph.end){
            endOffset = updateParagraph.end.offset[0];
            delFlg = updateParagraph.end.delete;
        }else{
            endOffset = updateParagraph.start.offset[0];
            delFlg = updateParagraph.start.delete;
        }

        endOffset = ost.extractOffset(endOffset, true);
        var pages = pageList;

        var nType = type;
        var cell = pageList.lookup(type, ost.extractCellOffset(offset));
        if(cell && cell.ref && cell.ref.__pageList){
            pages = cell.ref.__pageList;
            nType = "body";
        }

        if(delFlg){
            plusRowIndexForOffset(pages, endOffset, nType);
        }
        
        var nextParagraphInfo = pages.getNextParagraphInfo(endOffset, nType);

        updateParagraphIndex(pages, startOffset, nextParagraphInfo.ref,
            updateParagraph.start.element.__paragraphIndex, nType);
    }

    /**
     * 将偏移量中的行数加一
     * @param {*} pages
     * @param {*} offset 
     * @param {*} type
     */
    var plusRowIndexForOffset = function(pages, offset, type){
        if(offset.rowIndex + 1 > pages
            .getPage(offset.pageIndex).getLastRow(type, true).getIndex()){
            if(offset.pageIndex + 1 <= pages.getLastPage().getIndex()){
                offset.pageIndex += 1;
                offset.rowIndex = 1;
            }
        }else{
            offset.rowIndex += 1;
        }
    }

    /**
     * 将偏移量中的行数减一
     * @param {*} pages
     * @param {*} offset 
     * @param {*} type
     */
    var minusRowIndexForOffset = function(pages, offset, type){
        if(offset.rowIndex - 1 <= 0){
            if(offset.pageIndex - 1 > 0){
                offset.pageIndex -= 1;
                offset.rowIndex = pages.getPage(offset.pageIndex).getLastRow(type, true).getIndex();
            }
        }else{
            offset.rowIndex -= 1;
        }
    }

    /**
     * 检查需要保留的元素
     * @param {*} first 
     * @param {*} last
     * @param {*} type 
     * @param {*} deleteAction
     */
    var keepElement = function(first, last, type, deleteAction){
        var firstOffset = first.offset[0];
        var row = pageList.getPage(firstOffset.pageIndex).getRow(type, firstOffset.rowIndex - 1);
        var elementList = row.getElementList();
        var element = null;
 
        var textCount = 0;
        var emptyTextCount = 0;
        
        for(var i in elementList){
            element = elementList[i];
            if(element._sType == "sText"){
                textCount++;
                if(element.innerText == "" || element.innerText == null){
                    emptyTextCount++;
                }
            }
        }

        //获取被删除首个元素之前的最近一个段落信息
        // var prevParagraph = pageList.getPrevParagraphInfo(firstOffset, type);
        //获取最后一个段落
        var lastParagraph = pageList.getLastPage().getLastRow(type, true).getLastElement();

        if(last.element._sType == "sParagraph"){
            //最后一个段落元素不能删除
            if(last.element == lastParagraph){
                markDelete(deleteAction.getLastElement("sParagraph"), false);
            }
            // else{
            //     //删除的第一个元素的段落序号不等于最后一个段落元素的段落序号
            //     if(last.element.__paragraphIndex != first.element.__paragraphIndex){
            //         markDelete(deleteAction.getLastElement("sParagraph"), true);
            //     }
            // }
        }

        //如果文本全部删除，则保留第一个文本
        if(textCount == emptyTextCount){
            var lastOffset = last.offset[0];
            var text = deleteAction.getFirstElement("sText");

            var firstText = row.getFirstVisualElement("sText");
            if(!text || text.element !== firstText) return;

            //1.文本发生改变，
            //2.起始和结束行不相同
            //3.第一页第一行的首个文本元素
            if(text.oldContent != text.newContent ||
                (firstOffset.rowIndex != lastOffset.rowIndex) ||
                (text.offset.pageIndex == 1 && text.offset.rowIndex == 1)){
                markDelete(text, false);
            }

            //如果当前行第一个可见元素是该文本元素
            if(row.getFirstVisualElement() === text.element){
                //是最后一行
                let isLastRow = pageList.getLastPage().getLastRow(type).getIndex() == row.getIndex();
                //如果上一行是表格，并且当前行是最后一行，则该文本不能删除，
                if(firstOffset.rowIndex > 1){
                    let r = pageList.getPage(firstOffset.pageIndex).getRow(type, firstOffset.rowIndex - 2);
                    markDelete(text, !(r.getLastVisibleElement("sTable") != null && isLastRow));
                }else if(firstOffset.pageIndex > 1){
                    let r = pageList.getPage(firstOffset.pageIndex - 1).getLastRow(type);
                    markDelete(text, !(r.getLastVisibleElement("sTable") != null && isLastRow));
                }
            }
            
            //如果选择的开始和结束是同一行，且结束元素是段落元素
            //则段落元素则随着文本的删除而删除
            if(firstOffset.pageIndex == lastOffset.pageIndex &&
                firstOffset.rowIndex == lastOffset.rowIndex && 
                last.element._sType == "sParagraph"){
                
                markDelete(deleteAction.getLastElement("sParagraph"), text.delete);

                if(text.delete){
                    var offset = {...text.offset};
                    minusRowIndexForOffset(pageList, offset, type);

                    var isEndWithBreakline = pageList.getPage(offset.pageIndex)
                        .getRow(type, offset.rowIndex - 1).isEndWithBreakline();

                    if(isEndWithBreakline){
                        markDelete(text, false);
                        markDelete(deleteAction.getLastElement("sParagraph"), false);
                    }
                }
            }
        }
    }

    /**
     * 标记删除
     * @param {*} el 
     * @param {*} isDel
     */
    var markDelete = function(el, isDel){
        if(!setting.leaveTrace){
            el.delete = isDel;
        }

        if(isDel){
            if(setting.leaveTrace){
                el.element.delete = isDel;
            }
        }else{
            delete el.element.delete;
        }
    }

    /**
     * 移动光标
     * @param {*} sEvt 事件对象
     * @param {*} render 排版引擎
     * @param {*} direction 方向 ArrowLeft/ArrowRight/ArrowUp/ArrowDown
     * @param {*} notSkipEnd 光标到达一行末尾，是否跳过该位置
     */
    var moveCaret = function(sEvt, render, direction, notSkipEnd){
        var keyName = sEvt.keyName;
            
        sEvt.keyName = direction;
        render.locate(sEvt, {
            relocate: relocate, 
            notSkipEnd: notSkipEnd,
            closeBySelection: true,
            isHeadEditable: pageList.isHeadEditable()
        });
        sEvt.keyName = keyName;

        setLastPmdEvt(sEvt);
    }

    /**
     * 设置最新的焦点事件对象
     * @param {*} sEvt 
     */
    var setLastPmdEvt = function(sEvt){
        lme = sEvt;
        delete lme.keyName;
    }

    /**
     * 更新段落及所属元素的段落序号
     * @param {*} pages 分页集合
     * @param {*} offset 偏移量
     * @param {*} paragraph 替换的段落元素
     * @param {*} replaceParaIndex 当前被替换的段落序号
     * @param {*} type 
     * @param {*} isNew true 替换的段落是新的元素 false不是
     * @param {*} afterInvoke 参数(element, oldParagraphIndex)，更新元素段落序号后的回调函数
     */
    var updateParagraphIndex = function(pages, 
        offset, paragraph, replaceParaIndex, type, isNew, afterInvoke) {
        //当前所在段落配置
        var replaceParagraph = pages.getFirstPage()
            .getParagraphs()[type][replaceParaIndex];

        if(replaceParagraph){
            if(replaceParagraph.titleType){
                paragraph.titleType = replaceParagraph.titleType;
                delete replaceParagraph.titleType;
            }
            
            if(afterInvoke){
                afterInvoke(paragraph, {
                    style: {...paragraph.style, ...replaceParagraph.style},
                    relFor: replaceParagraph.__relFor
                });
            }else{
                //复制当前段落的样式
                paragraph.style = {...paragraph.style, ...replaceParagraph.style};
                paragraph.__relFor = replaceParagraph.__relFor;

                //双划线(留痕状态存在)
                if(!paragraph.delete && !paragraph.new){
                    delete paragraph.style.doubleDash;
                }
            }
            delete replaceParagraph.__relFor;
        }

        var paragraphIndex = paragraph.__paragraphIndex;
        if(isNew){
            //在页面中加入段落配置，所有页面段落配置共享，故取第一页添加即可
            paragraphIndex = pages.getFirstPage()
                .addParagraph(paragraph, type);
            paragraph.__paragraphIndex = paragraphIndex;
        }

        //获取前一个段落信息
        var info = pages.getPrevParagraphInfo({
            pageIndex: offset.pageIndex,
            rowIndex: offset.rowIndex
        }, type);

        //从前一个段落之后的元素开始遍历直到新的段落元素
        //更新其中所有元素的段落序号
        var startPageIndex = info.offset.pageIndex;
        var startRowIndex = info.offset.rowIndex + 1;
        var endPageIndex = offset.pageIndex;
        var endRowIndex = null;
        var endElementIndex = offset.elementIndex;
        var row = null;

        for(var i = startPageIndex; i <= endPageIndex; i++){
            if(i > info.offset.pageIndex){
                startRowIndex = 1;
            }

            if(i == endPageIndex){
                endRowIndex = offset.rowIndex;
            }else{
                endRowIndex = pages.getPage(i).getLastRow(type, true).getIndex();
            }

            for(var j = startRowIndex; j <= endRowIndex; j++){
                row = pages.getPage(i).getRow(type, j - 1);
                row.updateParagraphIndex(paragraphIndex, 
                    i == endPageIndex && j == endRowIndex 
                        ? endElementIndex 
                        : null,
                    afterInvoke
                );
            }
        }

    }

    /**
     * 处理重新排版后的结果
     * @param {*} sEvt 
     * @param {*} result 
     * @param {*} opt
     */
    var processRetypeResult = function(sEvt, render, result, opt){
        if(result.left != null){
            sEvt.offset = {
                left: result.left,
                top: result.top + DRIFT_LEN
            };
        }

        var pageIndex = null;

        if(sEvt.offset){
            pageIndex = sEvt.mutatePageIndex 
                ? sEvt.mutatePageIndex 
                : result.pageIndex;
        }

        var range = null;

        if(pageIndex){
            range = bindMethods.invoke("computePageRange", {
                pageSize: pageList.getPageSize(), 
                pageIndex: pageIndex
            });
        }else{
            range = bindMethods.invoke("getPageRange");
            pageIndex = range[0];
        }

        var pageRange = null;

        //此处来自页眉页脚的编辑，为了同步显示，故而页面全量刷新
        if(sEvt.mutatePageIndex){
            pageRange = range;
        }else{
            if(result.pageRange){
                pageRange = [];
                //不能随便改
                for(var i in range){
                    if(result.pageRange.indexOf(range[i]) > -1){
                        pageRange.push(range[i]);
                    }
                }
            }else{
                pageRange = range;
            }
        }

        this.invalidate({range: pageRange});
        documentPageChange(sEvt, pageIndex);

        if(pageIndex){
            sEvt.target = pageList
                .getPage(pageIndex)
                .search(sEvt.offset, null, {
                    exclude: "absolute",
                    isHeadEditable: pageList.isHeadEditable()
                }
            );
        }

        if(!result || result.left == null){
            sEvt.caret.blur();
        }else{
            var range = sEvt.selection && sEvt.selection.getRangeAt();
            if(!range || range.collapsed){
                render.locate(sEvt, {relocate: relocate});
                setLastPmdEvt(sEvt);
            }
        }

        contentChange(sEvt);
    }

    /**
     * 设置焦点
     * @param {*} opt
     */
    var focus = function(opt){
        if(!lme.target) return;
        var offset = ost.extractOffset(lme.target);
        lme.target = pageList.lookup(lme.target.position, offset);
        
        var render = renderList[curPage.getIndex()];
        if(!render){
            var pageRange = bindMethods.invoke("getPageRange");
            render = renderList[pageRange[0]];
        }

        var next = ost.extractOffset(offset, true);

        render.locate(lme, {
            locateContentIndex: next.contentIndex,
            ...opt
        });

        ost.mergeOffset(lme.target, offset);
    }

    /**
     * 插入批注
     * @param {*} option 
     */
    this.insertAnnotation = function(option){
        if(!canEdit(lme, true)) return;
        if(!range || range.collapsed) return;

        option = option ? option : {};

        var children = convert2Elements(option.content);
        if(!children) return;

        var type = range.__position;
        var offset = {...range.startOffset};
        var elementList = groupByElementForFragment(range);

        var modifyAction = ACTIONS.pushModifyAction(type);
        modifyAction.setSelectionRange(range, true);

        for(var i in elementList){
            el = elementList[i];

            if(el.element._sType == "sText"){
                modifyAction.divideTextForSelection(
                    el.element, 
                    el.offset, 
                    null, {
                        annotation: true,
                        annotationId: createUuid(),
                        annotationType: option.type ? option.type : "info",
                        annotationElements: children
                    }
                );
            }
        }

        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];
        var result = render.reformat(modifyAction.getElements(), 
            offset, type, pageList, ssDict.sActionType.MODIFY);

        var locateResult = render.locateElementOffset(
            ost.extractOffset(result.offset 
                ? result.offset 
                : result), 
            result.ref, pageList, type);
        
        processRetypeResult.call(this, lme, render, locateResult);
        
        //将当前事件目标对象设置为插入批注的对象
        ost.mergeOffset(lme.target, locateResult.offset);
        lme.target.ref = result.ref;
    }

    /**
     * 提取元素的属性
     * @param {*} element 
     */
    this.fetchAttributes = function(element){
        if(element && element._sType == "sLayer"){
            var type = ssDict.sPresentTypeMapElType[element.presentType];

            if(type == "sImage"){
                return {...element.attributes};
            }else{
                return {...element.getSubElement(type).attributes};
            }
        }
    }

    /**
     * 更新元素属性
     * @param {*} option 
     */
    this.updateAttributes = function(option){
        if(!option) return;

        var attributes = option.attributes;
        var result = null;

        //根据元素ID更新
        if(attributes.id){
            result = pageList.querySelector("#" + attributes.id);
        }
        //根据元素名称更新
        else if(attributes.name){
            result = pageList.querySelector("[name='" + attributes.name + "']", {queryAll: true});
        }

        var action = null;
        var offset = null;

        if(result){
            action = ACTIONS.pushModifyAction();
            //单个元素的属性更新
            if(!result.length){
                if(result.ref.style.position == "absolute"){
                    return updateAttrForAbsElement.call(this, result, option);
                }else{
                    offset = ost.extractOffset(result);
                    action.mutateWrapElement(result.ref, offset);
    
                    result.ref.attributes = attributes;
                }
            }else{
                //多个元素的属性更新 TODO待完成
                // for(let i = 0; i < result.length; i++){
                //     result[i].ref.attributes = attributes;
                // }
            }
        }else if(lme){
            if(attributes.position == "absolute"){
                return updateAttrForAbsElement.call(this, lme.target, option);
            }else{
                action = ACTIONS.pushModifyAction();

                //当前元素的属性更新
                let element = null;
    
                if(lme.belong){
                    element = lme.belong.element;
                    offset = lme.belong.offset;
                }else{
                    element = lme.target && lme.target.ref;
                    offset = ost.extractOffset(lme.target);
                } 
    
                if(element){
                    action.mutateWrapElement(element, offset);
                    element.attributes = attributes;
                }
            }
        }

        if(action && action.getElements().length > 0){
            //重新排版
            var pageRange = bindMethods.invoke("getPageRange");
            var render = renderList[pageRange[0]];
            
            var result = render.reformat(
                action.getElements(), offset, option.position, pageList, ssDict.sActionType.MODIFY);

            processRetypeResult.call(this, lme, render, result);
        }
    }
    
    /**
     * 处理绝对元素的属性更新
     * @param {*} target 
     * @param {*} option 
     */
    var updateAttrForAbsElement = function(target, option){
        //更新元素属性
        target.ref.attributes = option.attributes;

        let rect = target.ref.__boundRect;
        rect = rect[rect.length - 1];
        rect = rect[rect.length - 1];

        target.ref.style.left = rect.left;
        target.ref.style.top = rect.top + target.boundRect.top;
        
        //设定偏移量
        var offset = ost.extractOffset(target);

        offset.minPageIndex = offset.pageIndex;
        offset.minRowIndex = offset.rowIndex;

        var minOffset = {
            startPageIndex: offset.minPageIndex,
            startRowIndex: offset.minRowIndex
        };
        var render = renderList[curPage.getIndex()];
        var result = render.reformat2(offset, target.position, pageList, minOffset);

        var pageRange = bindMethods.invoke("getPageRange");
        for(let i in result.pageRange){
            if(pageRange.indexOf(result.pageRange[i]) < 0){
                result.pageRange[i] = null;
            }
        }

        this.invalidate({range: result.pageRange});
    }

    /**
     * 创建UUID
     * @returns 
     */
    var createUuid = function(){
        return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0,
            v = c == "x" ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    /**
     * 将内容转换成元素集合
     * @param {*} content 
     */
    var convert2Elements = function(content){
        if(content._sType == "sRoot"){
            if(content.children.length > 0){
                if(content.children[0]._sType == "sPageHead" ||
                   content.children[0]._sType == "sPageBody" ||
                   content.children[0]._sType == "sPageFoot"){
                    return content.children[0].children;
                }else{
                    return content.children;
                }
            }
        }

        return null;
    }

    /**
     * 设置光标到指定位置
     * @param {*} option 
     */
    this.setCursorByRect = function(option){
        let page = pageList.getPage(option.pageIndex);
        let target = page.search(option.boundRect);

        option.sEvt.offset = option.boundRect;
        option.sEvt.target = target;

        renderList[option.pageIndex].locate(option.sEvt);
    }

    /**
     * 设置当前元素样式
     * @param {*} style 样式
     * @param {*} range 选择范围
     * @param {*} join 和已存在的样式连接
     */
    this.setStyle = function(style, range, join) {
        if(!canEdit(lme, true)) return;
        if(!style || !range) return;

        if(style.style){
            style = {...style, ...style.style};
        }

        var innerStyle = {};
        var hasElementStyle = false;

        //过滤掉不支持的样式
        for(var i in style){
            if(ssDict.sStyles.indexOf(i) < -1) continue;
            innerStyle[i] = style[i];
            hasElementStyle = true;
        }

        if(!hasElementStyle) return;
        
        var elementList = null;
        var offset = null;
        var type = null;
        var modifyAction = null;

        if(range.collapsed){
            type = lme.target.position;
            offset = ost.extractOffset(lme.target);
            modifyAction = ACTIONS.pushModifyAction(type);
            
            elementList = [];

            if(offset.next){
                var cellOffset = ost.extractCellOffset(offset);
                var lookResult = pageList.lookup(range.__position, cellOffset);
                ost.mergeOffsetNext(cellOffset, {
                    startPageIndex: cellOffset.pageIndex,
                    startRowIndex: cellOffset.rowIndex
                });
                elementList.push({
                    element: lookResult.ref,
                    offset: [cellOffset]
                });
            }

            elementList.push({
                element: lme.target.ref,
                offset: [offset]
            });
        }else{
            type = range.__position;
            offset = {...range.startOffset};
            elementList = groupByElementForFragment(range);

            modifyAction = ACTIONS.pushModifyAction(type);
            modifyAction.setSelectionRange(range, true);
        }

        var el = null;
        var mutateStyle = null;
        var elStyle = null;
        //该选项的某些属性用来控制内部逻辑，某些属性用于多个元素的共享数值
        var opt = {
            //多个元素共享的属性值
            lastElementIndex: null,
            //如果光标在任意非选择区间修改样式，则创建一个新文本
            inTextEmptyCreate: range.collapsed
        };

        for(var i in elementList){
            el = elementList[i];
            elStyle = {...innerStyle};

            filterStyle(el.element, elStyle);

            if(join){
                for(var i in elStyle){
                    if(el.element.style[i] && el.element.style[i].indexOf(elStyle[i]) < 0){
                        elStyle[i] = el.element.style[i] + "|" + elStyle[i];
                    }
                }
            }

            if(elStyle.sub){
                elStyle.sup = false;
            }else if(elStyle.sup){
                elStyle.sub = false;
            }

            mutateStyle = {...el.element.style, ...elStyle};

            if(el.element._sType == "sText"){
                modifyAction.divideTextForSelection(el.element, el.offset, mutateStyle, opt);
            }else if(el.element._sType == "sLayer"){
                modifyAction.mutateLayer(el.element, el.offset[0], mutateStyle);
                opt.lastElementIndex++;
            }else if(el.element._sType == "sTableCell"){
                modifyAction.mutateTableCell(el.element, el.offset[0], mutateStyle);
            }
        }

        if(modifyAction.getElements().length == 0) return;
        
        modifyAction.setOffset(offset);

        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];
        var result = render.reformat(modifyAction.getElements(), 
            offset, type, pageList, ssDict.sActionType.MODIFY);

        if(!range.collapsed){
            var lastInElement = modifyAction.getLastInElement();
            if(lastInElement){
                range.endOffset = getElementEndOffset(lastInElement);
            }
            startSelection.call(this, {
                selection: bindMethods.invoke("getSelection"),
                target: lme.target
            });
            
            modifyAction.setSelectionRange(range);

            documentPageChange(lme, result.pageIndex);
            this.invalidate({range: pageRange});
        }else{
            var locateResult = render.locateElementOffset(
                ost.extractOffset(result.offset 
                    ? result.offset 
                    : result), 
                result.ref, pageList, type);
            
            processRetypeResult.call(this, lme, render, locateResult);
            
            //将当前事件目标对象设置为修改样式的对象
            ost.mergeOffset(lme.target, locateResult.offset);
            lme.target.ref = result.ref;
        }
    }

    /**
     * 过滤元素不支持的样式
     * @param {*} element
     */
    var filterStyle = function(element, style){
        for(var i in style){
            if(!ssDict.sStylesSupport[i] || 
                ssDict.sStylesSupport[i].elementTypes.indexOf(element._sType) < 0){
                delete style[i];
            }
        }
    }

    /**
     * 将fragments按元素分组
     * @param {*} range
     * @param {*} opt
     * @returns 
     */
    var groupByElementForFragment = function(range, opt){
        if(!range.startOffset) return;

        var fragments = pageList.extractFragment(
            range.startOffset,
            range.endOffset,
            range.__position,
            {...opt}
        );

        var fragment = null;
        var element = null;
        var elementList = [];
        var existElements = [];
        var item = null;
        var index = -1;

        //按元素分组
        for(var i in fragments){
            for(var j in fragments[i]){
                fragment = fragments[i][j];

                if(fragment.table){
                    index = existElements.indexOf(fragment.element);
                    if(index < 0){
                        item = {
                            element: fragment.element,
                            table: fragment.table,
                            offset: []
                        };
                        elementList.push(item);
                        existElements.push(fragment.element);
                    }else{
                        item = elementList[index];
                    }
                    
                    item.offset.push(fragment.offset);
                }else{
                    if(element != fragment.element){
                        item = {
                            element: fragment.element,
                            offset: []
                        };
                        elementList.push(item);
                        existElements.push(fragment.element);

                        element = fragment.element;
                    }

                    item.offset.push(fragment.offset);
                }
            }
        }

        return elementList;
    }

    /**
     * 设置段落样式
     * @param {*} style 
     * @param {*} range
     */
    this.setParagraphStyle = function(style, range){
        if(!canEdit(lme, true)) return;
        
        var hasParagraphStyle = false;

        for(var i in ssDict.sParagraphStyles){
            if(style[ssDict.sParagraphStyles[i]] == undefined) continue;
            hasParagraphStyle = true;
            break;
        }

        if(!hasParagraphStyle) return;

        var offset = null;
        var type = null;

        var lastElementEnd = null;
        var lastElement = null;

        var infos = null;

        if(range.collapsed){
            if(!lme || !lme.target) return;

            type = lme.target.position;
            offset = ost.extractOffset(lme.target);

            var paragraph = getSingleParagraphInfo(offset, type);
            infos = [paragraph];
        }else{
            type = range.__position;
            var fragments = range.__fragments;

            infos = extractParagraphsInFragments(fragments, null, null, type);
            delete infos.__paragraphIndexs;

            //获取最后一个段落，因为可能只选到段落文本，而未选到段落元素
            if(infos.length == 0 || infos.length > 1){
                var fragment = fragments[fragments.length - 1];
                fragment = fragment[fragment.length - 1];

                if(isGeneralElement(fragment.element)){
                    var lastParagraph = getSingleParagraphInfo(fragment.offset, type);
                    var isContain = false;
        
                    for(var i in infos){
                        if(infos[i].ref == lastParagraph.ref){
                            isContain = true;
                            break;
                        }
                    }
        
                    if(!isContain){
                        infos.push(lastParagraph);
                    }
                }
            }

            //寻找选择区域最后一个元素
            var lookResult = pageList.lookup(type, range.endOffset);
            lastElement = lookResult.ref;
            lastElementEnd = getElementRangeEnd(lastElement, 
                ost.extractOffset(range.endOffset, true));
        }

        var modifyAction = ACTIONS.pushModifyAction(type);
        if(!range.collapsed){
            modifyAction.setSelectionRange(range, true);
        }

        var info = null;
        for(var i in infos){
            info = infos[i];
            modifyAction.mutateParagraph(info.ref, info.offset, style);
        }

        //重新排版
        var pageRange = bindMethods.invoke("getPageRange");
        var render = renderList[pageRange[0]];
        
        var firstOffset = infos[0].offset;
        var lastOffset = infos[infos.length - 1].offset;

        offset = {
            pageIndex: firstOffset.startPageIndex 
                ? firstOffset.startPageIndex 
                : firstOffset.pageIndex,
            rowIndex: firstOffset.startRowIndex 
                ? firstOffset.startRowIndex 
                : firstOffset.rowIndex,
            minPageIndex: lastOffset.pageIndex,
            minRowIndex: lastOffset.rowIndex
        };

        modifyAction.setOffset(offset);

        var result = render.reformat(modifyAction.getElements(), 
            offset, type, pageList, ssDict.sActionType.MODIFY);

        if(!range.collapsed){
            offset = render.getOffsetForElement(lastElement, {
                range: {
                    end: lastElementEnd
                }
            });

            if(range.endOffset.next){
                ost.mergeOffsetNext(range.endOffset, offset);
                if(range.endOffset.pageIndex != offset.pageIndex){
                    ost.updatePageIndexExceptLastNext(range.endOffset, offset.pageIndex);
                }
                var lookResult = pageList.lookup(type, range.endOffset,{
                    autoMatch: true,
                    element: lastElement
                });
                ost.mergeOffset(range.endOffset, lookResult.offset);
            }else{
                ost.mergeOffset(range.endOffset, offset);
            }
        }

        documentPageChange(lme, result.pageIndex);
        this.invalidate({range: pageRange});

        if(!range.collapsed){
            startSelection.call(this, {
                selection: bindMethods.invoke("getSelection"),
                target: {}
            });
            focus({notDoSelection: true});
        }else{
            focus();
        }
    }

    /**
     * 是否是一般元素
     * @param {*} element 
     */
    var isGeneralElement = function(element){
        return element._sType == "sText" ||
            element._sType == "sLayer";
    }

    /**
     * 根据偏移量获取段落信息
     * @param {*} offset 
     * @param {*} type
     * @returns 
     */
    var getSingleParagraphInfo = function(offset, type){
        if(offset.next){
            var lookResult = pageList.lookup(type, ost.extractCellOffset(offset));
            var cellOffset = ost.extractOffset(offset, true);
            var paragraph = lookResult.ref.__pageList.getParagraphInfo(cellOffset, "body");

            ost.mergeOffsetNext(offset, paragraph.offset);
            paragraph.offset = offset;

            return paragraph;
        }else{
            return pageList.getParagraphInfo(offset, type);
        }
    }

    /**
     * 从选择片段中抽取段落元素
     * @param {*} fragments 
     * @param {*} paragraphs
     * @param {*} indexes
     * @param {*} type
     */
    var extractParagraphsInFragments = function(fragments, paragraphs, indexes, type){
        paragraphs = paragraphs ? paragraphs : [];
        indexes = indexes ? indexes : [];

        if(fragments instanceof Array && 
            fragments[fragments.length - 1] instanceof Array){
            for(var i in fragments){
                for(var j in fragments[i]){
                    extractParagraph(fragments[i][j], paragraphs, indexes, type);
                }
            }
        }else{
            for(var i in fragments){
                extractParagraph(fragments[i], paragraphs, indexes, type);
            }
        }
        
        return paragraphs;
    }

    /**
     * 抽取段落
     * @param {*} fragment 
     * @param {*} paragraphs 
     * @param {*} indexes
     * @param {*} type
     */
    var extractParagraph = function(fragment, paragraphs, indexes, type){
        if(fragment.element._sType == "sTableCell"){
            let inds = [];
            extractParagraphsInFragments(fragment.fragment, paragraphs, inds, "body");
        }else if(indexes.indexOf(fragment.element.__paragraphIndex) < 0){
            paragraphs.push(getSingleParagraphInfo(fragment.offset, type));
            indexes.push(fragment.element.__paragraphIndex);
        }
    }

    /**
     * 根据偏移量获取元素内容在元素中的位置
     * @param {*} element 
     * @param {*} offset 
     */
    var getElementRangeEnd = function(element, offset){
        var end = 0;
        if(element._sType == "sText"){
            for(var i in element.__texts){
                if(i > offset.pageIndex) break;
                for(var j in element.__texts[i]){
                    if(j > offset.rowIndex) break;
                    if(j < offset.rowIndex){
                        end += element.__texts[i][j].length;
                    }else{
                        end += offset.contentIndex + 1;
                    }
                }
            }
            return end;
        }else{
            return 0;
        }
    }

    /**
     * 设置标题
     * @param {*} option 
     */
    this.setTitle = function(option){
        if(!option || ssDict.sTitleTypes.indexOf(option.type) < 0) return;
        if(!lme || !lme.target) return;

        let offset = ost.extractOffset(lme.target);
        let paragraph = pageList.getParagraphInfo(offset);
        let type = lme.target.position;

        if(option.type != "Text"){
            paragraph.ref.titleType = option.type;
        }else{
            delete paragraph.ref.titleType;
        }

        if(option.style){
            let offset = {
                pageIndex: paragraph.offset.startPageIndex,
                rowIndex: paragraph.offset.startRowIndex
            };
            let els = pageList.getParagraphChildren(
                paragraph.ref.__paragraphIndex, offset, type);

            let action = ACTIONS.pushModifyAction();
            
            for(let j in els){
                if(els[j].ref._sType != "sText") continue;
                action.mutateTextStyle(els[j].ref, els[j].offset, {...option.style});
            }

            let pageRange = bindMethods.invoke("getPageRange");
            let render = renderList[pageRange[0]];

            let result = render.reformat(action.getElements(), 
                offset, type, pageList, ssDict.sActionType.MODIFY);
            
            let resultOffset = ost.extractOffset(result);
            ost.mergeOffset(lme.target, resultOffset);
        }

        this.invalidate({range: [paragraph.offset.startPageIndex]});

        return lme.target.pageIndex;
    }

    /**
     * 获取标题
     * @param {*} option 
     */
    this.getTitles = function(option){
        option = option ? option: {};

        let range = option.range ? option.range : null;
        let titles = {};
        let text = "";
        let boundRect = null;

        pageList.forEach((page, pageIndex)=>{
            if(range && range.indexOf(pageIndex) < 0){
                return;
            }

            page.forEach((row, index, type)=>{
                if(type != "body") return;
                row.forEach((element)=>{
                    if(element.__texts){
                        text += element.__texts[pageIndex][index];
                    }

                    if(!boundRect){
                        boundRect = {...element.__boundRect[pageIndex][index]};
                        boundRect.top += row.getBoundRect().top;
                    }

                    if(element._sType == "sParagraph"){
                        if(element.titleType){
                            if(!titles[pageIndex]){
                                titles[pageIndex] = [];
                            }

                            titles[pageIndex].push({
                                titleType: element.titleType,
                                titleContent: text,
                                boundRect: boundRect,
                                pageIndex: pageIndex
                            });
                        }
                        boundRect = null;
                        text = "";
                    }
                });
            });
        });

        return titles;
    }

    /**
     * 处理方向键
     * @param {*} sEvt 
     * @returns 
     */
    var processDirection = function(sEvt, render){
        sEvt.target = lme.target;
        sEvt.baseOffset = lme.baseOffset;
        sEvt.offset = lme.offset;

        if(!sEvt.direction || !lme) return;

        var isHeadEditable = pageList.isHeadEditable();

        //使用shift键加方向键选择内容
        if(sticky && sEvt.direction){
            if(!isSelection(sEvt)){
                setSelection.call(this, sEvt, 1);

                var keyName = sEvt.keyName;
                sEvt.keyName = null;
                
                render.locate(sEvt, { 
                    relocate: relocate, 
                    closeBySelection: true,
                    isHeadEditable: isHeadEditable
                });

                sEvt.keyName = keyName;
                setSelection.call(this, sEvt, 2);
            }

            render.locate(sEvt, { 
                relocate: relocate, 
                closeBySelection: true,
                isHeadEditable: isHeadEditable
            });

            startSelection.call(this, sEvt);
        }else{
            render.locate(sEvt, { 
                relocate: relocate,
                isHeadEditable: isHeadEditable,
                clearSelection: ()=>{
                    setSelection.call(this, sEvt);
                    setSelection.call(this, sEvt, 1);
                }
            });
        }

        setScroll(sEvt, 2);
    }

    /**
     * 设置滚动
     * @param {*} sEvt 
     * @param {*} type
     */
    var setScroll = function(sEvt, type){
        if(type == 1){
            if(!sEvt.nativeEvt) return;

            var clearAutoScroll = function(){
                if(bindMethods.__interval){
                    clearInterval(bindMethods.__interval);
                    delete bindMethods.__interval;
                }
            };
    
            var gt = sEvt.nativeEvt.pageY > sEvt.outRect.top + sEvt.outRect.height;
            var lt = sEvt.nativeEvt.pageY < sEvt.outRect.top;
    
            if(gt || lt){
                clearAutoScroll();
    
                var increment = gt ? 20 : -20;
                var scrollTop = 0;
    
                bindMethods.__interval = setInterval(() => {
                    if(sEvt.selection.getRangeAt().__start > 0){
                        scrollTop = bindMethods.invoke("getScrollTop");
                        bindMethods.invoke("scrollTo", scrollTop + increment);
                        if(scrollTop == bindMethods.invoke("getScrollTop")){
                            clearAutoScroll();
                        }
                    }else{
                        clearAutoScroll();
                    }
                }, 10);
            }
        }else if(type == 2){
            if(!sEvt.locateRect || !sEvt.outRect) return;
            var scrollTop = bindMethods.invoke("getScrollTop");
            var currentTop = sEvt.locateRect.top; 

            if(scrollTop + sEvt.outRect.height < currentTop + sEvt.locateRect.height) {
                bindMethods.invoke("scrollTo", sEvt.locateRect.top + 
                    sEvt.locateRect.height - sEvt.outRect.height);
            }else if(scrollTop > currentTop){
                bindMethods.invoke("scrollTo", sEvt.locateRect.top);
            }
        }
    }

    /**
     * 光标重定位
     * @param {*} sEvt 
     * @param {*} opt
     */
    var relocate = function(sEvt, opt){
        opt = opt ? opt : {};

        if(opt.mergeOffset){
            opt.mergeOffset();
        }

        var boundRect = null;
        var next = sEvt.target;
        var unpackInfo = null;
        var type = sEvt.target.position;
        var nType = sEvt.target.position;
        var pages = pageList;

        if(next.next){
            for(next = next.next; next.next != null; next = next.next){
            }

            unpackInfo = pages.getPage(sEvt.target.pageIndex)
                .unpacking(sEvt.target.position, sEvt.target);

            if(opt){
                if(opt.resetOffset){
                    sEvt.offset = {
                        //left取绝对定位
                        left: unpackInfo.offset.left,
                        top: 0
                    };
                }
            }

            pages = unpackInfo.pageList;
            boundRect = unpackInfo.boundRect;

            next.rowspan = unpackInfo.rowspan;
            next.colspan = unpackInfo.colspan;
            nType = "body";
        }

        var page = pages.getPage(sEvt.target.pageIndex);
        var pageChange = 0;

        if(!page){
            page = pages.getPage(sEvt.target.pageIndex - 1);
            if(!page) {
                next.rowIndex = 1;
                if(!relocateInTable(sEvt, next, unpackInfo)){
                    resetOffset(sEvt);
                }
                return;
            }else{
                next.pageIndex = page.getIndex();
                next.rowIndex = page.getRowCount(nType);
            }

            pageChange = -1;
        }else if(next.rowIndex < 1){
            page = pages.getPage(page.getIndex() - 1);

            if(!page) {
                next.rowIndex = 1;
                if(!relocateInTable(sEvt, next, unpackInfo)){
                    resetOffset(sEvt);
                }
                return;
            }else{
                next.pageIndex = page.getIndex();
                next.rowIndex = page.getRowCount(nType);
            }

            pageChange = -1;
        }else if(next.rowIndex > page.getRowCount(nType)){
            var pageIndex = page.getIndex();
            page = pages.getPage(pageIndex + 1);

            if(!page) {
                next.rowIndex = pages.getPage(pageIndex).getRowCount(nType);
                if(!relocateInTable(sEvt, next, unpackInfo)){
                    resetOffset(sEvt);
                }
                return;
            }else{
                next.pageIndex = page.getIndex();
                next.rowIndex = 1;
            }

            pageChange = 1;
        }

        if(page){
            delete sEvt.keyName;

            if(pageChange){
                documentPageChange(sEvt, page.getIndex());

                var row = null;

                if(pageChange == -1){
                    row = page.getRow(nType, page.getRowCount(nType) - 1);
                }else if(pageChange == 1){
                    row = page.getRow(nType, 0);
                }

                sEvt.offset.top = row.getBoundRect().top + DRIFT_LEN;
            }

            var option = {
                containParagraph: true,
                isHeadEditable: opt && opt.isHeadEditable,
                plus: opt.keyName == "ArrowRight" || opt.keyName == "ArrowDown"
            };

            if(unpackInfo){
                var target = sEvt.target;
 
                sEvt.offset.left -= unpackInfo.offset.left;

                var isMouseEvt = sEvt.eventType == "mousedown" || 
                    sEvt.eventType == "mousemove" || 
                    sEvt.eventType == "dblclick";

                //点击产生的纵坐标是相对画布的坐标，键盘移动的纵坐标是相对父元素的坐标
                if(isMouseEvt){
                    sEvt.offset.top -= unpackInfo.offset.top;
                }

                sEvt.target = page.search(sEvt.offset, nType, option);

                if(pageChange){
                    var rowIndex = boundRect[page.getIndex()].length - 1;
                    target.rowIndex = rowIndex;
                    target.pageIndex = sEvt.target.pageIndex;
                    unpackInfo = pageList
                        .getPage(page.getIndex()).unpacking(sEvt.target.position, target);
                }

                sEvt.target.boundRect.left += unpackInfo.offset.left;
                sEvt.target.boundRect.top += unpackInfo.offset.top;
                sEvt.target.boundRect.offsetLeft = unpackInfo.offset.left;
                sEvt.target.boundRect.offsetTop = unpackInfo.offset.top;

                if(sEvt.target.prevTarget){
                    sEvt.target.prevTarget.boundRect.left += unpackInfo.offset.left;
                    sEvt.target.prevTarget.boundRect.top += unpackInfo.offset.top;
                    sEvt.target.prevTarget.boundRect.offsetLeft = unpackInfo.offset.left;
                    sEvt.target.prevTarget.boundRect.offsetTop = unpackInfo.offset.top;

                    if(unpackInfo.boundRect.verticalOffsetHeight){
                        sEvt.target.prevTarget.boundRect.top += unpackInfo.boundRect.verticalOffsetHeight;
                        sEvt.target.prevTarget.boundRect.offsetTop += unpackInfo.boundRect.verticalOffsetHeight;
                    }
                }

                sEvt.offset.left += unpackInfo.offset.left;
                if(isMouseEvt){
                    sEvt.offset.top += unpackInfo.offset.top;
                }

                if(unpackInfo.boundRect.verticalOffsetHeight){
                    sEvt.target.boundRect.top += unpackInfo.boundRect.verticalOffsetHeight;
                    sEvt.target.boundRect.offsetTop = unpackInfo.boundRect.verticalOffsetHeight;
                    sEvt.offset.top += unpackInfo.boundRect.verticalOffsetHeight;
                }

                var excuted = false;

                opt.mergeOffset = (callback)=>{
                    updateTargetProps(sEvt, target);
                    if(callback){
                        callback(sEvt);
                    }
                    setLastPmdEvt(sEvt);
                    excuted = true;
                };

                renderList[page.getIndex()].locate(sEvt, opt);

                if(!excuted){
                    updateTargetProps(sEvt, target);
                    setLastPmdEvt(sEvt);
                }
            }else{
                sEvt.target = page.search(sEvt.offset, nType, option);
                renderList[page.getIndex()].locate(sEvt, opt);
                setLastPmdEvt(sEvt);
            }

            //页眉、页脚的表格内部光标定位，需要将位置设置为最外层的区域类型
            if(type != sEvt.target.position){
                sEvt.target.position = type;
            }
        }
    }

    /**
     * 重置偏移量
     * @param {*} sEvt 
     */
    var resetOffset = function(sEvt){
        sEvt.offset = {
            left: sEvt.target.boundRect.left,
            top: sEvt.target.boundRect.top
        }
        setLastPmdEvt(sEvt);
    }

    /**
     * 光标在表格内重定位
     * @param {*} sEvt 
     * @param {*} next 
     * @param {*} unpackInfo
     * @param {*} opt
     * @returns true表示在表格范围定位成功 false不在表格范围内
     */
    var relocateInTable = function(sEvt, next, unpackInfo, opt){
        if(next.tableRowIndex == null) return false;

        next.rowIndex = 1;

        //向右或向下
        if(sEvt.keyName == "ArrowRight" || sEvt.keyName == "ArrowDown"){
            var tableRowIndex = next.tableRowIndex;
            var tableColIndex = next.tableColIndex;

            if(sEvt.keyName == "ArrowRight"){
                if(tableColIndex + next.colspan < next.tableColCount){
                    tableRowIndex = unpackInfo.tableRowIndex;
                    tableColIndex = unpackInfo.tableColIndex + unpackInfo.colspan;
                }else{
                    tableRowIndex += 1;
                    tableColIndex = 0;
                }
            }else if(sEvt.keyName == "ArrowDown"){
                tableRowIndex = unpackInfo.tableRowIndex + unpackInfo.rowspan;
            }

            //超出表格范围
            if(tableRowIndex > unpackInfo.table.getRows().length - 1){
                var lastRow = pageList.getPage(sEvt.target.pageIndex)
                    .getLastRow(sEvt.target.position);
                var rowIndex = lastRow.getIndex();
                var boundRect = unpackInfo.boundRect[sEvt.target.pageIndex][sEvt.target.rowIndex];

                if(sEvt.target.rowIndex < rowIndex){
                    sEvt.target.rowIndex += 1;
                }else if(sEvt.target.pageIndex < pageList.getLastPage().getIndex()){
                    sEvt.target.pageIndex += 1;
                    sEvt.target.rowIndex = 1;
                }else{
                    return false;
                }

                sEvt.offset.top = unpackInfo.offset.top + boundRect.height + DRIFT_LEN;
                
                relocateInPage(sEvt, pageList);

                return true;
            }

            next.tableRowIndex = tableRowIndex;
            next.tableColIndex = tableColIndex;
            
            next.rowIndex = 1;
            next.elementIndex = 0;
            next.contentIndex = -1;

            var range = getTableRowRangeInPage(unpackInfo.table, sEvt.target.pageIndex);
            var rows = unpackInfo.table.getRows();

            if(next.tableRowIndex > range.end){
                sEvt.target.pageIndex = rows[next.tableRowIndex].__boundRect.length - 1;
                sEvt.target.rowIndex = 1;

                documentPageChange(sEvt, sEvt.target.pageIndex);
            }

            if(sEvt.keyName == "ArrowRight"){
                if(unpackInfo.pageList.getPageSize() > 1){
                    var pageIndex = unpackInfo.pageList.getFirstPage().getIndex();

                    next.pageIndex = pageIndex;
                    sEvt.target.pageIndex = pageIndex;
                    sEvt.target.rowIndex = unpackInfo.boundRect[pageIndex].length -1;

                    documentPageChange(sEvt, pageIndex);
                }

                passSpanCell(sEvt, next);
            }

            if(!opt){
                opt = {};
            }

            opt.resetOffset = true;
        }
        //向左或向上
        else if(sEvt.keyName == "ArrowLeft" || sEvt.keyName == "ArrowUp"){
            var tableRowIndex = next.tableRowIndex;
            var tableColIndex = next.tableColIndex;

            if(sEvt.keyName == "ArrowLeft"){
                tableRowIndex = unpackInfo.tableRowIndex;
                tableColIndex = unpackInfo.tableColIndex - 1;

                if(tableColIndex < 0){
                    tableRowIndex -= 1;
                    tableColIndex = next.tableColCount - 1;
                }
            }else if(sEvt.keyName == "ArrowUp"){
                tableRowIndex = unpackInfo.tableRowIndex - 1;
            }

            //超出当前表格范围
            if(tableRowIndex < 0){
                if(sEvt.target.rowIndex > 1){
                    sEvt.target.rowIndex -= 1;
                }else if(sEvt.target.pageIndex > 1){
                    sEvt.target.pageIndex -= 1;
                }else{
                    return false;
                }

                sEvt.offset = {
                    top: unpackInfo.offset.top - DRIFT_LEN,
                    left: sEvt.offset.left
                };

                relocateInPage(sEvt, pageList);

                return true;
            }

            next.tableRowIndex = tableRowIndex;
            next.tableColIndex = tableColIndex;

            var rowRange = getTableRowRangeInPage(unpackInfo.table, sEvt.target.pageIndex);
            if(next.tableRowIndex < rowRange.start){
                sEvt.target.pageIndex -= 1;
                sEvt.target.rowIndex = 1;

                documentPageChange(sEvt, sEvt.target.pageIndex);
            }

            if(sEvt.keyName == "ArrowLeft"){
                passSpanCell(sEvt, next, true);
            }

            var info = pageList.getPage(sEvt.target.pageIndex)
                .unpacking(sEvt.target.position, sEvt.target);
            var row = info.pageList.getLastPage().getLastRow("body");
            var eleRect = row.getActualBoundRect(row.getLastVisibleElement());

            next.rowIndex = row.getIndex();

            //下一个单元格是分页状态
            //某些单元格内容并未填充满，内容分页和包围盒分页不是完全一致的，
            //内容分页数会小于包围盒的分页数
            if(info.pageList.getPageSize() > 1 ||
                info.pageList.getLastPage().getIndex() < sEvt.target.pageIndex){

                sEvt.target.pageIndex = info.pageList.getLastPage().getIndex();
                sEvt.target.rowIndex = info.boundRect[sEvt.target.pageIndex].length -1;
                next.pageIndex = sEvt.target.pageIndex;

                info = pageList.getPage(sEvt.target.pageIndex)
                    .unpacking(sEvt.target.position, sEvt.target);
                
                documentPageChange(sEvt, sEvt.target.pageIndex);
            }

            sEvt.offset.left = info.offset.left + eleRect.left + eleRect.width;
            sEvt.offset.top = info.offset.top + row.getBoundRect().top + eleRect.top;
        }

        relocate(sEvt, opt);

        return true;
    }

    /**
     * 光标在页面重定位
     * @param {*} sEvt 
     * @param {*} pages 
     */
    var relocateInPage = function(sEvt, pages){
        sEvt.target = pages.getPage(sEvt.target.pageIndex).search(sEvt.offset);
        sEvt.offset = {
            top: sEvt.target.boundRect.top,
            left: sEvt.keyName == "ArrowRight"
                ? sEvt.target.rowRect.left 
                : sEvt.keyName == "ArrowLeft"
                    ? sEvt.target.rowRect.left + 
                      sEvt.target.rowRect.width
                    : sEvt.offset.left
        };

        sEvt.target = pages.getPage(sEvt.target.pageIndex).search(sEvt.offset);

        var boundRect = sEvt.target.boundRect;
        if(boundRect.letterSpacing){
            sEvt.offset.left += boundRect.letterSpacing * (
                sEvt.target.isLast 
                    ? sEvt.target.text.length - 1
                    : sEvt.target.text.length
            )
        }

        delete sEvt.eventType;
        delete sEvt.keyName;

        renderList[sEvt.target.pageIndex].locate(sEvt);
        setLastPmdEvt(sEvt);
    }

    /**
     * 通知文档当前页发生改变
     * @param {*} sEvt
     * @param {*} pageIndex 
     */
    var documentPageChange = function(sEvt, pageIndex){
        bindMethods.invoke("setHandle", pageIndex);
        sEvt.baseOffset = bindMethods.invoke("getOffset", {
            handle: pageIndex,
            autoCreate: true
        });
    }

    /**
     * 获取表格在指定页的行范围
     * @param {*} table 
     * @param {*} pageIndex 
     * @returns 
     */
    var getTableRowRangeInPage = function(table, pageIndex){
        var range = {
            start: null,
            end: null
        };

        var rows = table.getRows();
        var flg = 0;
        
        for(var i = 0; i < rows.length; i++){
            if(rows[i].__boundRect[pageIndex]){
                if(flg == 0){
                    range.start = i;
                    flg = 1;
                }
            }else if(flg == 1){
                range.end = i - 1;
                break;
            }
        }

        if(range.start != null && range.end == null){
            range.end = rows.length - 1;
        }

        return range;
    }

    /**
     * 跳过被合并掉的单元格
     * @param {*} sEvt 事件对象
     * @param {*} next 最内层子元素偏移量
     * @param {*} toLeft true 方向向左 false 方向向右
     */
    var passSpanCell = function(sEvt, next, toLeft){
        var info = null;
        while(true){
            info = pageList.getPage(sEvt.target.pageIndex)
                .unpacking(sEvt.target.position, sEvt.target);
            
            if(!info){
                break;
            }

            if(next.tableRowIndex > info.tableRowIndex &&
                next.tableRowIndex <= info.tableRowIndex + info.rowspan){
                
                if(toLeft){
                    if(info.tableColIndex > 0){
                        next.tableColIndex = info.tableColIndex - 1;
                    }else{
                        next.tableRowIndex -= 1;
                        next.tableColIndex = next.tableColCount - 1;
                    }
                }else{
                    if(info.tableColIndex + info.colspan < next.tableColCount){
                        next.tableColIndex = info.tableColIndex + info.colspan;
                    }else{
                        next.tableRowIndex += 1;
                        next.tableColIndex = 0;
                    }
                }
                
                continue;
            }else{
                break;
            }
        }
    }

    /**
     * 更新目标属性
     * @param {*} sEvt 
     * @param {*} root 
     */
    var updateTargetProps = function(sEvt, root){
        var next = ost.extractOffset(sEvt.target);
        root = ost.extractOffset(root);
        
        ost.mergeOffsetNext(root, next);
        ost.mergeOffset(sEvt.target, root);
    }

    /**
     * 设置粘滞状态
     * @param {*} sEvt 
     * @param {*} status 
     * @returns 
     */
    var setSticky = function(sEvt, status){
        if(sEvt.keyName != "Shift") return false;
        sticky = status;
        return true;
    }

    /**
     * 定位目标
     * @param {*} sEvt 事件对象
     * @param {*} page 当前页
     * @param {*} render 当前排版引擎
     */
    var locateTarget = function(sEvt, page, render, opt){
        if(!sEvt.offset) return;
        if(isSelection(sEvt)){
            setLastPmdEvt(sEvt);
            sEvt.target = page.search(sEvt.offset, 
                sEvt.selection.getRangeAt().__position, {containParagraph: true});
            render.locate(sEvt, { relocate: relocate, ...opt });
            startSelection.call(this, sEvt);
        }else{
            setSelection.call(this, sEvt, 2);
        }
    }

    /**
     * 判断当前区域是否可编辑
     * @param {*} sEvt 
     * @returns 
     */
    var isEditable = function(sEvt){
        return !sEvt.target || 
           (sEvt.target.position == "body" && !pageList.isHeadEditable()) ||
            sEvt.target.position != "body" && pageList.isHeadEditable();
    }

    /**
     * 是否可以编辑通过
     * @param {*} sEvt 
     * @returns 
     */
    var canEditPass = function(sEvt){
        if(!isEditable(sEvt)) {
            if(sEvt.target.position != "body"){
                sEvt.target = curPage.search(sEvt.offset, null, {
                    position: "body"
                });
                return true;
            }else{
                return false;
            }
        }

        return true;
    }

    /**
     * 设置区域可编辑
     * @param {*} sEvt 
     */
    var setEditable = function(sEvt){
        if(!sEvt.target) return;
        if(sEvt.target.position == "body"){
            if(pageList.isHeadEditable()){
                pageList.setHeadEditable(false);
                document.invalidate();
                sEvt.isHeadEditable = false;
            }
        }else if(sEvt.target.position == "head" || 
            sEvt.target.position == "foot"){
            if(!pageList.isHeadEditable()){
                pageList.setHeadEditable(true);
                document.invalidate();
                sEvt.isHeadEditable = true;
                onHf = true;
            }
        }

        if(sEvt.target){
            setLastPmdEvt(sEvt);
        }
    }

    /**
     * 判断当前鼠标是否作用在selection区域
     * @param {*} sEvt 
     * @param {*} render
     */
    var isOnSelection = function(sEvt, render){
        onSel = false;

        if(sticky) return onSel;

        var range = sEvt.selection.getRangeAt();
        if(range.collapsed || !range.__fragments || !sEvt.target || !sEvt.target.ref) return;

        render.locate(sEvt, {
            notDoSelection: true, 
            notMoveCaret: true
        });

        let offset = ost.extractOffset(sEvt.target);

        onSel = ost.amongOffset(range.startOffset, range.endOffset, offset);

        return onSel;
    }

    /**
     * 最后一次选择区域所在的页范围
     */
    var lastSelPageRange = null;
    
    /**
     * 选择器开始选择
     * @param {*} sEvt 
     */
    var startSelection = function(sEvt, opt){
        range = sEvt ? sEvt.selection.getRangeAt() : range;

        var flg = !range         
            || range.collapsed      
            || !range.endOffset     
            || (sEvt && !sEvt.target);

        if(flg){
            if(!opt || !opt.notInvalidate){
                if(range.__fragments){
                    clearSelection();
                    this.invalidate({range: getSelectPageRange(range)});
                }
            }
            return;
        } 

        clearSelection();

        //根据选择区域抽取页面片段
        var fragments = pageList.extractFragment(
            range.startOffset,
            range.endOffset,
            range.__position,
            {containParagraph: true}
        );

        range.__fragments = fragments;
        
        var isHeadFoot = null;

        if(pageList.isHeadEditable() &&
          (range.__position == "head" || range.__position == "foot")){
            isHeadFoot = true;
        }

        for(var i in fragments){
            if(isHeadFoot){
                renderList[sEvt.target.pageIndex].getPainter().drawSelection(fragments[1]);
            }else{
                if(!renderList[i]) continue;
                renderList[i].getPainter().drawSelection(fragments[i]);
            }
        }

        //设定本地需要重绘的页面
        var pageRange = [];
        var pRange = bindMethods.invoke("getPageRange");

        for(var i in pRange){
            if(pRange[i] >= range.startOffset.pageIndex &&
               pRange[i] <= range.endOffset.pageIndex){
                pageRange.push(pRange[i]);
            }
        }

        if(!opt || !opt.notInvalidate){
            //上次在选择区域的页，这次不再，则需要重绘该页
            let tempRange = pageRange.slice();
            for(let i in lastSelPageRange){
                if(tempRange.indexOf(lastSelPageRange[i]) < 0){
                    tempRange.push(lastSelPageRange[i]);
                }
            }
            this.invalidate({range: tempRange});
            lastSelPageRange = pageRange;
        }

        if(sEvt && sEvt.caret){
            sEvt.caret.blur(true);
        }
    }

    /**
     * 获取选择区域涵盖的页面范围
     * @param {*} range 
     * @returns 
     */
    var getSelectPageRange = function(range){
        if(!range.__fragments) return null;

        var pageRange = [];

        for(var i in range.__fragments){
            pageRange.push(parseInt(i));
        }

        return pageRange;
    }

    /**
     * 清除选择区域
     * @returns 
     */
    var clearSelection = function(){
        return plm.clear(ssDict.sPaintLayerLevel.SELECTION);
    }

    /**
     * 清除选择区域和重置range对象，并触发重绘
     */
    var invalidateSelection = function(){
        range.reset();
        
        let pageRange = plm.getHandleByLevel(ssDict.sPaintLayerLevel.SELECTION);

        if(clearSelection()){
            this.invalidate({range: pageRange});
        }
    }

    /**
     * 设置选择器状态
     * @param {*} sEvt 
     * @param {*} value 
     * @param {*} opt
     */
    var setSelection = function(sEvt, value, opt) {
        range = sEvt ? sEvt.selection.getRangeAt() : range;
        if(!range) return;

        if(value == 1 && !range.__start) {
            var pageRange = plm.getHandleByLevel(ssDict.sPaintLayerLevel.SELECTION);

            if(clearSelection()){
                this.invalidate({range: pageRange});
            }

            let startOffset = range.startOffset;
            let startContainer = range.startContainer;

            range.reset();

            if(sEvt.target){
                range.__start = value;
                range.__position = sEvt.target.position;
            }

            if(opt && opt.notResetStartOffset){
                range.__startOffset = startOffset;
                range.__startContainer = startContainer;
                range.startOffset = startOffset;
                range.startContainer = startContainer;
            }
        } else if(value == 2 && range.__start == 1) {
            range.__start = value;
        } else if(!value && range.__start){
            delete range.__start;
        }
    }

    /**
     * 选择器是否处于选择状态
     * @returns 
     */
    var isSelection = function(sEvt){
        return sEvt.selection.getRangeAt().__start == 2;
    }

    /**
     * 全选
     * @param {*} sEvt 
     */
    var selectAll = function(sEvt){
        var type = sEvt.target.position;
        var range = sEvt.selection.getRangeAt();

        range.__position = type;

        range.startOffset = {
            pageIndex: 1,
            rowIndex: 1,
            elementIndex: 0,
            contentIndex: -1
        }

        var lastPage = pageList.getLastPage();
        var lastRow = lastPage.getLastRow(type, true);

        range.endOffset = {
            pageIndex: lastPage.getIndex(),
            rowIndex: lastRow.getIndex(),
            elementIndex: lastRow.getElementList().length - 1,
            contentIndex: 0
        }

        startSelection.call(this, sEvt);
    }

    /**
     * 自动选择
     * @param {*} sEvt 
     * @param {*} render 
     */
    var autoSelect = function(sEvt, render){
        if(!sEvt.target) return;

        updatePageIndexIfNotBody(sEvt, 1);

        render.locate(sEvt, {relocate: relocate});

        var type = sEvt.target.position;
        var range = sEvt.selection.getRangeAt();

        range.__position = type;

        if(sEvt.target.ref._sType == "sText" && 
           sEvt.target.ref.innerText){
            var result = getOffsetForSelect(sEvt);
            range.startOffset = result.startOffset;
            range.endOffset = result.endOffset;
        }
        
        updatePageIndexIfNotBody(sEvt);

        startSelection.call(this, sEvt);

        if(!range.collapsed){
            //确保光标隐藏
            setTimeout(()=>{
                sEvt.caret.blur(true);
            }, 50);
        }
    }

    /**
     * 获取选择元素的偏移量
     * @param {*} sEvt 
     * @returns 
     */
    var getOffsetForSelect = function(sEvt){
        var type = sEvt.target.position;
        var nType = sEvt.target.position;
        var pages = pageList;

        var offset = ost.extractOffset(sEvt.target, true);
        var startOffset = { ...offset };
        var endOffset = { ...offset };

        var cellOffset = ost.extractCellOffset(sEvt.target);
        var cell = pageList.lookup(type, cellOffset);
        if(cell && cell.ref && cell.ref.__pageList){
            pages = cell.ref.__pageList;
            nType = "body";
        }

        var char = null;
        var currentType = null;

        var text = "";
        var startIndex = null;
        var element = sEvt.target.ref;
        var flg = false;

        //从当前往前遍历
        for(var i = offset.pageIndex; ; i--){
            if(!element.__texts[i]) break;

            startOffset.pageIndex = i;

            for(var j = offset.rowIndex; ; j--){
                text = element.__texts[i][j];
                if(text == null) break;

                startIndex = i == offset.pageIndex && j == offset.rowIndex 
                    ? offset.contentIndex : text.length - 1;

                startOffset.rowIndex = j;
                startOffset.elementIndex = pages
                    .getPage(i).getRow(nType, j - 1).indexOf(element);
                startOffset.contentIndex = startIndex;

                for(var k = startIndex; k > -1; k--){
                    char = text.substring(k, k + 1);
                    if(!currentType){
                        currentType = getCharType(char);
                        startOffset.contentIndex = k - 1;
                    }else if(getCharType(char) == currentType){
                        startOffset.contentIndex = k - 1;
                    }else{
                        flg = true;
                        break;
                    }
                }

                if(flg) break;
            }

            if(flg) break;
        }

        flg = false;

        //从当前往后遍历
        for(var i = offset.pageIndex; ; i++){
            if(!element.__texts[i]) break;

            endOffset.pageIndex = i;

            for(var j = offset.rowIndex; ; j++){
                text = element.__texts[i][j];
                if(text == null) break;

                startIndex = i == offset.pageIndex && j == offset.rowIndex 
                    ? offset.contentIndex : 0;
                startIndex = startIndex < 0 ? 0 : startIndex;

                endOffset.rowIndex = j;
                endOffset.elementIndex = pages
                    .getPage(i).getRow(nType, j - 1).indexOf(element);
                endOffset.contentIndex = startIndex;

                for(var k = startIndex; k < text.length; k++){
                    char = text.substring(k, k + 1);
                    if(!currentType){
                        currentType = getCharType(char);
                        endOffset.contentIndex = k;
                    }else if(getCharType(char) == currentType){
                        endOffset.contentIndex = k;
                    }else{
                        flg = true;
                        break;
                    }
                }

                if(flg) break;
            }

            if(flg) break;
        }

        var _rootOffsetForStart = ost.extractOffset(sEvt.target);
        ost.mergeOffsetNext(_rootOffsetForStart, startOffset);

        var _rootOffsetForEnd = ost.extractOffset(sEvt.target);
        ost.mergeOffsetNext(_rootOffsetForEnd, endOffset);

        return {
            startOffset: _rootOffsetForStart,
            endOffset: _rootOffsetForEnd
        };
    }

    /**
     * 获取字符类型
     * @param {*} char 
     * @returns 
     */
    var getCharType = function(char){
        if(isEnglishChar(char)){
            return "EN";
        }else if(isChineseChar(char)){
            return "CN";
        }else if(isNumberChar(char)){
            return "NU";
        }else{
            return "OT";
        }
    }

    /**
     * 判断单个字符是否为英文字符
     * @param {*} char 
     * @returns 
     */
    var isEnglishChar = function(char){
        return /[a-zA-Z]/.test(char);
    }

    /**
     * 判断单个字符是否为中文字符
     * @param {*} char 
     * @returns 
     */
    var isChineseChar = function(char){
        return /[\u4e00-\u9fa5]/.test(char);
    }

    /**
     * 判断单个字符是否为数字
     * @param {*} char 
     * @returns 
     */
    var isNumberChar = function(char){
        return /[0-9]/.test(char);
    }

    /**
     * 复制内容
     * @param {*} sEvt 
     */
    var copy = function(sEvt, render) {
        if(!sEvt.selection || !sEvt.textInput) return;

        if(sEvt.target && sEvt.target.ref._sType == "sLayer"){
            // let offset = ost.extractOffset(sEvt.target);
            // range.startOffset = ost.mergeOffsetNext(offset, {contentIndex: -1});
            // range.endOffset = ost.mergeOffsetNext(
            //     ost.extractOffset(offset), {contentIndex: 0});
        }else if(sEvt.selection.getRangeAt().collapsed){
            return;
        }

        var el = null;
        var elementList = groupByElementForFragment(range, {
            containParagraph: true
        });
        
        for(var i = 0; i < elementList.length; i++){
            el = elementList[i];

            if(el.offset.length > 0 && el.element._sType == "sText"){
                var offset = null;
                var next = null;
                var text = document.createElement("sText");

                text = cloneElement(el.element);
                
                let hasPlaceholder = text.placeholder != null && text.placeholder.length > 0;
                let hasInnerText = text.innerText != null && text.innerText.length > 0;

                if(hasInnerText || (!hasInnerText && !hasPlaceholder)){
                    text.innerText = "";

                    for(var j in el.offset){
                        offset = el.offset[j];
                        next = ost.extractOffset(offset, true);
    
                        text.innerText += el.element
                            .__texts[next.pageIndex][next.rowIndex]
                            .substring(next.start + 1, next.end + 1);
                    }
                }

                elementList.splice(i, 1, {element: text});
            }
        }

        sEvt.textInput.copy(elementList);
    }

    /**
     * 克隆元素
     * @param {*} element 
     * @returns 
     */
    var cloneElement = function(element){
        var clone = {};
        
        for(var i in element){
            if(i.indexOf("__") > -1) continue;
            if(element[i] != null && typeof(element[i]) == "object"){
                clone[i] = cloneElement(element[i]);
            }else{
                clone[i] = element[i];
            }
        }

        if(typeof(element.constructor) == "function"){
            element.constructor.call(clone);
        }

        return clone;
    }

    /**
     * 剪切内容
     * @param {*} sEvt 
     * @param {*} render 
     * @returns 
     */
    var cut = function(sEvt, render) {
        copy(sEvt, render);
        return deleteSelectContent.call(this, sEvt, render);
    }

    /**
     * 粘贴内容
     * @param {*} sEvt 
     */
    var paste = function(sEvt, render) {
        if(!sEvt || !sEvt.target || !sEvt.data) return;

        for(i in sEvt.data.children){
            if(sEvt.data.children[i]._sType == "sTable" && sEvt.target.next){
                sEvt.data.children.splice(i, 1);
            }
        }

        var offset = ost.extractOffset(sEvt.target);
        var range = sEvt.selection.getRangeAt();
        //当前内容处于被选择状态
        if(!range.collapsed){
            deleteSelectContent.call(this, sEvt, render);
            lme.data = sEvt.data;
            sEvt = lme;
        }
        
        var type = sEvt.target.position;
        var action = ACTIONS.pushAddAction(type);
        var merge = false;
        var pages = pageList;

        if(offset.next){
            var cell = pageList.lookup(type, ost.extractCellOffset(offset));
            pages = cell.ref.__pageList;
        }

        if(sEvt.target.ref._sType == "sText"){
            action.mutateText(sEvt.target.ref, offset);
            var el = action.getElements()[0];
            merge = el.oldContent != el.newContent;
        }else{
            action.add(sEvt.target.ref, ost.extractOffset(sEvt.target));
        }
        
        var mainIndex = null;
        var mutateCount = 0;
        var paragraphIndex = null;
        var element = null;
        var children = sEvt.data.children;

        //当前段落
        const paragraph = pages.getFirstPage().getParagraph(
            sEvt.target.ref.__paragraphIndex, type);
        var firstParagraphIndex = null;

        for(var i = children.length - 1; i >= 0; i--){
            element = children[i];
            mutateCount = 0;

            if(element._sType == "sParagraph"){
                paragraphIndex = pages.getFirstPage().addParagraph(element, type);
                element.__paragraphIndex = paragraphIndex;
                firstParagraphIndex = paragraphIndex;
            }else{
                if(paragraphIndex == null){
                    paragraphIndex = paragraph.__paragraphIndex;
                }

                if(element._sType == "sText"){
                    if(element.innerText.length > MAX_TEXT_LENGTH){
                        var textList = splitLongText(element.innerText, element.style, 
                            paragraphIndex);
                        children.splice(i, 1, ...textList);
                        mutateCount = textList.length - 1;
                    }
                }

                element.__paragraphIndex = paragraphIndex;
            }

            if(isInvisibleElement(element)) continue;

            if(mainIndex == null){
                mainIndex = i + mutateCount;
            }else if(mutateCount > 0){
                mainIndex += mutateCount;
            }
        }

        var lastEl = action.getLastElement();
        var lastOffset = null;

        for(var i = 0; i < children.length; i++){
            //这里的offset对于被设置的元素是不准确的，但对于新增元素仅用作判断
            lastOffset = ost.extractOffset(lastEl.offset);
            action.add(children[i], lastOffset, null, i == mainIndex);
        }

        if(merge){
            var newText = document.createElement("sText");
            newText.__paragraphIndex = paragraph.__paragraphIndex;
            action.addText(newText, true, true);
        }
                    
        var elements = action.getElements();

        //粘贴的首个元素是表格
        if(children[0]._sType == "sTable"){
            if(elements[0].element._sType == "sText"){
                //当前行文本元素为空
                if(!elements[0].element.innerText){
                    elements.splice(0, 1);
                }else{
                    //不为空，则插入段落换行
                    element = document.createElement("sParagraph")
                    firstParagraphIndex = pages.getFirstPage().addParagraph(element, type);
                    element.__paragraphIndex = firstParagraphIndex;
                    action.add(element, null, null, null, 1);
                }
            }
        }

        //最后一个元素是段落
        if(children[children.length - 1]._sType == "sParagraph"){
            if(isEndInParagraph(sEvt.target)){
                var newText = document.createElement("sText");
                newText.__paragraphIndex = paragraph.__paragraphIndex;
                action.add(newText, null, null, true);
            }
        }

        element = elements[elements.length - 1].element;
        
        //最后一个粘贴的元素是表格
        if(element._sType == "sTable"){
            element = document.createElement("sText");
            element.__paragraphIndex = paragraph.__paragraphIndex;
            action.add(element, null, null, true, elements.length);
        }

        if(firstParagraphIndex != null){
            var next = ost.extractOffset(offset, true);
            var firstParagraph = pages.getFirstPage().getParagraph(firstParagraphIndex, type);

            updateParagraphIndex(pages, next, firstParagraph, null, type);
        }

        action.setOffset(offset);

        //对当前页进行排版
        var result = render.reformat(
            elements,
            offset, 
            type,
            pageList,
            ssDict.sActionType.INSERT
        );

        processRetypeResult.call(this, sEvt, render, result);

        return result;
    }

    /**
     * 判断当前位置是否是元素所在段落的末尾
     * @param {*} target 
     * @returns 
     */
    var isEndInParagraph = function(target){
        if(target.ref.innerText != null){
            var len = target.ref.innerText.length;
            len = len.length > 0 ? len - 1 : -1;
            return target.contentIndex == len && (
                target.isEndWithParagraph ||
                target.isEndWithBreakline
            );
        }else{
            return target.contentIndex == 0 && (
                target.isEndWithParagraph ||
                target.isEndWithBreakline
            );
        }
    }

    /**
     * 判断是否是不可见元素
     * @param {*} element 
     */
    var isInvisibleElement = function (element) {
        var flg = (element.style &&
            element.style.display == "none");
        
        flg = flg || element._sType == "sParagraph";
        flg = flg || element._sType == "sBreakline"

        return flg;
    }

    /**
     * 撤销
     * @param {*} sEvt 
     * @param {*} render
     */
    var undo = function(sEvt, render) {
        var action = ACTIONS.undo();
        if(!action) return;

        var actType = action.getActType();

        if(action.beforeReverse && action.beforeReverse()){
            action.beforeReverse()();
        }

        var reverse = action.reverse();
        var result = null;

        if(reverse instanceof Array){
            for(var i in reverse){
                result = undoSingle.call(this, sEvt, render, reverse[i], actType);
            }
        }else{
            result = undoSingle.call(this, sEvt, render, reverse, actType);
        }

        return result;
    }

    /**
     * 撤销单个区域
     * @param {*} sEvt 
     * @param {*} render 
     * @param {*} reverse 
     * @param {*} actType 
     */
    var undoSingle = function(sEvt, render, reverse, actType){
        if(reverse.delete){
            actType = ssDict.sActionType.DELETE;
        }else if(reverse.insert){
            actType = ssDict.sActionType.INSERT;
        }

        var result = null;
        if(actType != ssDict.sActionType.EMPTY){
            result = render.reformat(
                reverse.elements,
                reverse.offset, 
                reverse.type,
                pageList,
                actType,
                { notDeleteFirst: true }
            );
        }else{
            result = render.reformat2(
                reverse.offset, 
                reverse.type,
                pageList,
                {
                    startPageIndex: reverse.offset.pageIndex,
                    startRowIndex: reverse.offset.rowIndex
                }
            );
        }

        var range = sEvt.selection && sEvt.selection.getRangeAt();
        if(range){
            clearSelection();
            range.reset();
        }

        processRetypeResult.call(this, sEvt, render, result);

        if(range && reverse.selectionRange){
            range.__position = reverse.selectionRange.__position;
            range.startOffset = reverse.selectionRange.startOffset;
            range.endOffset = reverse.selectionRange.endOffset;

            startSelection.call(this, lme);

            documentPageChange(lme, result.pageIndex);
            this.invalidate({range: bindMethods.invoke("getPageRange")});
        }

        return result;
    }

    /**
     * 重做
     * @param {*} sEvt 
     * @param {*} render 
     */
    var redo = function(sEvt, render) {
        var action = ACTIONS.redo();
        if(!action) return;

        var actType = action.getActType();

        if(action.beforeRecover && action.beforeRecover()){
            action.beforeRecover()();
        }

        var recover = action.recover();
        var result = null;
        
        if(recover instanceof Array){
            for(var i in recover){
                result = redoSingle.call(this, sEvt, render, recover[i], actType);
            }
        }else{
            result = redoSingle.call(this, sEvt, render, recover, actType);
        }

        return result;
    }

    /**
     * 
     * @param {*} sEvt 
     * @param {*} render 
     * @param {*} recover 
     * @param {*} actType 
     */
    var redoSingle = function(sEvt, render, recover, actType){
        var result = null;

        if(actType != ssDict.sActionType.EMPTY){
            result = render.reformat(
                recover.elements,
                recover.offset, 
                recover.type,
                pageList,
                actType,
                recover.opt
            );
        }else{
            result = render.reformat2(
                recover.offset, 
                recover.type,
                pageList,
                {
                    ...recover.opt,
                    startPageIndex: recover.offset.pageIndex,
                    startRowIndex: recover.offset.rowIndex
                }
            );
        }

        var range = sEvt.selection && sEvt.selection.getRangeAt();
        if(range){
            clearSelection();
        }

        processRetypeResult.call(this, sEvt, render, result);

        if(range && recover.selectionRange){
            range.__position = recover.selectionRange.__position;
            range.startOffset = recover.selectionRange.startOffset;
            range.endOffset = recover.selectionRange.endOffset;

            startSelection.call(this, lme);

            documentPageChange(lme, result.pageIndex);
            this.invalidate({range: bindMethods.invoke("getPageRange")});
        }

        return result;
    }

    /**
     * 获取元素的终末偏移量
     * @param {*} target 
     */
    var getElementEndOffset = function(target){
        var element = target.ref;
        var offset = {
            pageIndex: null,
            rowIndex: null,
            elementIndex: null,
            contentIndex: null
        };

        offset.pageIndex = element.__boundRect.length - 1;
        offset.rowIndex = element.__boundRect[offset.pageIndex].length - 1;

        if(element._sType == "sText"){
            offset.contentIndex = element.__texts[offset.pageIndex][offset.rowIndex].length - 1;
        }else{
            offset.contentIndex = 1;
        }

        var pages = pageList;
        var eleOffset = target.offset 
            ? ost.extractOffset(target.offset) 
            : ost.extractOffset(target);

        if(eleOffset.next){
            var lookupResult = pageList.lookup(target.position, ost.extractCellOffset(eleOffset));
            pages = lookupResult.ref.__pageList;
            offset.elementIndex = pages.getPage(offset.pageIndex)
                .getRow("body", offset.rowIndex - 1).indexOf(element);
        }else{
            offset.elementIndex = pages.getPage(offset.pageIndex)
                .getRow(target.position, offset.rowIndex - 1).indexOf(element);
        }

        offset = ost.mergeOffsetNext(eleOffset, offset);

        return offset;
    }

    /**
     * 自定义导出功能
     * @param {*} opt 
     */
    this.customExport = function(opt){
        opt = opt ? opt : {};

        opt.setting = setting;
        opt.plm = new sPaintLayerManager();

        var ratioTime = opt.ratioTime ? opt.ratioTime : 1;
        var pages = opt.pageList ? opt.pageList : pageList;
        var pageSize = pages.getPageSize();

        pages.forEach((page, pageIndex)=>{
            if(opt.range.indexOf(pageIndex) < 0){ 
                return; 
            };

            var canvas = document.createCanvas();   
            var render = new sLayoutEngine(
                new sPainter(canvas), 
                page, 
                scale * ratioTime, 
                opt
            );

            render.getPainter().clear();

            //清除相关图层
            clearPaintLayer(opt.plm, pageIndex);

            if(opt.export && opt.export.exportPage){
                opt.export.exportPage(page);
            }

            var option = null;
            var pIndex = null;

            //批注区域
            var annotationProp = getAnnotationProp(page);

            //绘制水印
            if(opt.range.watermark){
                render.getPainter().drawWatermark(
                    pageList.getWatermark(), 
                    page.getBoundRect(), 
                    pageIndex, {
                        ...annotationProp,
                        ...opt.export
                    }
                );
            }

            //绘制底纹
            if(opt.range.texture){
                render.getPainter().drawTexture(
                    pageList.getTexture(), 
                    page.getBoundRect(), 
                    pageIndex, {
                        ...annotationProp,
                        ...opt.export
                    }
                );
            }

            //绘制行内元素
            page.forEach((row, index, type)=>{
                if(type == "head" && !opt.range.pageHead){
                    return;
                }

                if(type == "foot" && !opt.range.pageFoot){
                    return;
                }

                if(type == "body" && opt.range.rowIndexOf(pageIndex, index) < 0){ 
                    return; 
                };

                pIndex = pageIndex;
                option = {
                    type: type,
                    annotationProp: annotationProp,
                    elementBorderDisplay: setting.elementBorderDisplay,
                    pageIndex: pageIndex,
                    pageSize: pageSize,
                    ...opt.export
                };

                if(type == "head" || type == "foot"){
                    if(isOutRectForHeadFoot(page, type, row)) return;
                    pIndex = 1;
                    option.pageIndex = pageIndex;
                }
                
                option.isParagraphEnd = row.isEndWithParagraph();

                //绘制差异行
                let diffRows = pages.getDiffRow(index, pageIndex, type);
                if(diffRows){
                    let diffRow = null;
                    for(var i in diffRows){
                        diffRow = diffRows[i];
                        diffRow.row.forEach((element)=>{
                            paintElement(element, render, diffRow.row, index, pIndex, type, {...option});
                        });
                        paintDiffRow.call(this, diffRow, render, { backDisplay: true, minus: true });
                    }

                    paintDiffRow.call(this, {row: row}, render, { lastest: true, plus: true });
                }

                if(row.containENAndCN()){
                    option.containENAndCN = true;
                }

                //绘制正文行
                row.forEach((element)=>{
                    paintElement(element, render, row, index, pIndex, type, {...option});
                }, {
                    ignoreInvisible: true, 
                    containParagraph: true
                });
            });

            //绘制绝对定位元素(目前只支持层元素)
            page.forEachForAbsolute((element, type, index)=>{
                render.getPainter().drawLayer(element, null, pageIndex);
            });

            render.getPainter().drawLayout(page, {
                head: isLayoutVisible("head"),
                foot: isLayoutVisible("foot"),
                annotationProp: annotationProp,
                isHeadEditable: pageList.isHeadEditable()
            });

            render.getPainter().drawPaintLayer();
        })
    }

    /**
     * 导出元素
     * @param {*} types 指定导出元素类型
     * @param {*} opt 可选项
     * @returns 
     */
    this.export = function(opt) {
        opt = opt ? opt : {};

        var rang = bindMethods.invoke("getPageRange");
        var render = renderList[rang[0]];

        var data = null;

        if(opt.fragment){
            data = {};

            var types = ["body", "head", "foot"];
            for(var i in types){
                if(opt.fragment.indexOf(types[i]) > -1){
                    data[types[i]] = [];
                }
            }
        }else{
            data = {
                head: [],
                body: [],
                foot: []
            };
        }

        if(!data) return;

        var existsTable = [];
        var cloneCallback = (key, value) => {
            if(key.indexOf("__") == 0){
                return undefined;
            }else if(key == "_pType"){
                return undefined;
            }else if(!value){
                return undefined;
            }else if(key == "src"){
                return value.src
            }

            return value;
        };

        pageList.forEach((page, pageIndex)=>{
            page.forEach((row, index, type)=>{
                if(data[type] == null) return;
                if(pageIndex > 1 && (type == "head" || type == "foot")) return;

                row.forEach((element)=>{
                    if(data[type].indexOf(element) > -1) return;
                    if(element._sType == "sTable"){
                        if(existsTable.indexOf(element) > -1) return;
                        existsTable.push(element);
                        element = exportTable(element);
                    }else if(element._sType == "sLayer"){
                        if(element.presentType == ssDict.sPresentType.PAGE_NUMBER){
                            element = bindMethods.invoke("cloneData", element, cloneCallback);
                            render.getPainter().updateVariable(element.children[0], pageIndex);
                        }else if(element.presentType == ssDict.sPresentType.EDITABLE){
                            let table = element.getSubElement("sTable");
                            let tableExt = exportTable(table);
                            let index = element.children.indexOf(table);

                            element = bindMethods.invoke("cloneData", element, cloneCallback);
                            element.children.splice(index, 1, tableExt);
                        }
                    }
                    data[type].push(element);
                });
            });

            page.forEachForAbsolute((element, type)=>{
                data[type].push(element);
            });
        });

        var props = pageList.getAllProps();
        for(let i in props){
            data[i] = props[i];
        }

        return data;
    }

    /**
     * 导出表格
     * @param {*} element 
     */
    var exportTable = function(element){
        var columns = element.getColumns();
        var rows = element.getRows();

        element = JSON.parse(JSON.stringify(element, (key, value) => {
            if(key.indexOf("__") == 0){
                return undefined;
            }
            return value;
        }));
        
        element.columns = columns;
        element.rows = [];

        var row = null;
        var cells = null;
        var cell = null;
        var rowObj = null;
        var cellObj = null;

        for(var i in rows){
            row = rows[i];

            rowObj = {
                _sType: "sTableRow",
                cells: []
            };

            if(row.style){
                rowObj.style = row.style;
            }

            if(row.head){
                rowObj.head = row.head;
            }

            element.rows.push(rowObj);

            cells = row.getCells();
            for(var j in cells){
                cell = cells[j];

                cellObj = {
                    _sType: "sTableCell",
                    children: []
                };

                if(cell.style){
                    cellObj.style = cell.style;
                }

                cellObj.rowspan = cell.rowspan;
                cellObj.colspan = cell.colspan;
        
                rowObj.cells.push(cellObj);
                
                for(var k in cell.children){
                    if(cell.children[k]._sType == "sTable"){
                        cellObj.children.push(exportTable(cell.children[k]));
                    }else{
                        cellObj.children.push(cell.children[k]);
                    }
                }
            }
        }

        return element;
    }

    /**
     * 获取文本元素内容
     * @param {*} position 文档页面区域 head,foot,body
     */
    this.getText = function(position){
        var texts = [];
        var existsTable = [];

        pageList.forEach((page, pageIndex)=>{
            page.forEach((row, index, type)=>{
                if(position && type != position) return;

                row.forEach((element)=>{
                    if(element._sType == "sTable"){
                        if(existsTable.indexOf(element) > -1) return;
                        existsTable.push(element);
                        getTextFromTable(this, element);
                    }else if(element._sType == "sText"){
                        if(!element.__texts) return;
                        texts.push(element.__texts[pageIndex][index]);
                    }else if(element._sType == "sParagraph"){
                        texts.push("\r\n");
                    }else if(element._sType == "sBreakline"){
                        texts.push("\n");
                    }
                });
            });
        });

        return texts;
    }

    /**
     * 从表格中获取文本
     * @param {*} table 
     */
    var getTextFromTable = function(table){
    }

    /**
     * 查找
     * @param {*} findExp 查找的字符串内容
     * @param {*} option 可选项
     */
    this.find = function(findExp, option){
        option = option ? option : {};

        if(option.cache == null){
            option.cache = finding.cache;
        }

        var franges = {};
        var result = {
            count: 0
        };

        if(!finding.cache || !option.cache){
            finding.cache = createFindCache(null, pageList);
        }

        for(var i in finding.cache){
            var area = finding.cache[i];
            if(!area) continue;

            if(option.findAreas && 
               option.findAreas.indexOf(i) < 0) continue;

            franges[i] = [];

            findInText(area.texts, findExp, franges[i], result, option);
            findInTable(area.tables, findExp, franges[i], result, option);
        }

        if(range){
            clearSelection();
            range.reset();
        }

        clearFindZone();

        finding.fragments = {};
        var areaFrag = null;
        var setStart = false;

        //高亮显示查找区域
        for(var area in franges){
            areaFrag = [];
            finding.fragments[area] = areaFrag;

            for(var i in franges[area]){
                var frange = franges[area][i];

                //根据查找区域抽取页面片段
                var fragments = pageList.extractFragment(
                    frange.startOffset,
                    frange.endOffset,
                    area,
                    {containParagraph: true}
                );

                setStart = false;

                for(var j in fragments){
                    if(fragments[j].length == 0) continue;
                    if(!setStart){
                        for(var k in fragments[j]){
                            fragments[j][k].findStart = true;
                            break;
                        }
                        setStart = true;
                    }
                    
                    if(!areaFrag[j]){
                        areaFrag[j] = fragments[j];
                    }else{
                        areaFrag[j] = areaFrag[j].concat(fragments[j]);
                    }
                }
            }
        }
        
        if(!option.notInvalidate){
            paintFindFragment();
            this.invalidate({ range: bindMethods.invoke("getPageRange")});
        }

        result.fragments = finding.fragments;
        return result;
    }

    /**
     * 在文本中查找
     * @param {*} texts 文本数组
     * @param {*} findExp 查找表达式
     * @param {*} franges 分片集合
     * @param {*} result 查找结果
     * @param {*} option 可选项
     */
    var findInText = function(texts, findExp, franges, result, option){
        for(var j in texts){
            var text = texts[j];
            var info = findIndexInText(text.content, findExp, option);

            if(info.indexList.length == 0) continue;

            result.count += info.indexList.length;

            var frange = {};
            var len = info.len;
            var prev = null;
            var lastIndex = 0;
            var passLen = 0;
            
            for(var k in info.indexList){
                var index = info.indexList[k];
                var end = index + len;

                for(var m = lastIndex; m < text.offsets.length; m++){
                    var offset = text.offsets[m];
                    var offsetChanged = !isOffsetEqualForFind(prev, offset);

                    if(!frange.startOffset && index >= offset.start && index <= offset.end){
                        frange.startOffset = ost.mergeOffsetNext({...offset}, {
                            contentIndex: passLen > 0 || offsetChanged
                                ? index - (prev.end + 2) 
                                : index - 1
                        });
                    }

                    if(!frange.endOffset && end >= offset.start && end <= offset.end){
                        frange.endOffset = ost.mergeOffsetNext({...offset}, {
                            contentIndex: passLen > 0 || offsetChanged
                                ? end - (prev.end + 2)
                                : end - 1
                        });
                    }

                    if(offsetChanged){
                        passLen = prev.end;
                    }

                    if(frange.startOffset && frange.endOffset){
                        franges.push(frange);
                        frange = {};
                        lastIndex = m;
                        break;
                    }

                    prev = {...offset};
                }
            }
        }
    }

    /**
     * 在表格中查找
     * @param {*} tables 表格内容数组
     * @param {*} findExp 查找表达式
     * @param {*} franges 分片集合
     * @param {*} result 查找结果
     * @param {*} option 可选项
     */
    var findInTable = function(tables, findExp, franges, result, option){
        if(!tables) return;
        
        var cell = null;
        var frges = null;

        for(var i in tables){
            for(var j in tables[i]){
                cell = tables[i][j];
                frges = [];
                
                findInTable(cell.body.tables, findExp, frges, result, option);
                findInText(cell.body.texts, findExp, frges, result, option);
                
                for(var k in frges){
                    frges[k].startOffset = ost.mergeOffsetNext(
                        ost.extractOffset(cell.body.offset), frges[k].startOffset);
                    frges[k].endOffset = ost.mergeOffsetNext(
                        ost.extractOffset(cell.body.offset), frges[k].endOffset);

                    franges.push(frges[k]);
                }
            }
        }
    }

    /**
     * 替换
     * @param {*} findExp 匹配的内容或表达式
     * @param {*} replaceExp 替换的内容或表达式
     * @param {*} option 可选项
     */
    this.replace = function(findExp, replaceExp, option){
        option = option ? option : {};

        var areas = ["head", "foot", "body"];
        var pageRange = bindMethods.invoke("getPageRange");
        var action = ACTIONS.pushReplaceAction();

        for(var i in areas){
            option.findAreas = [areas[i]];

            this.find(findExp, {
                ...option, 
                cache: false,
                notInvalidate: true
            });

            if(!finding.fragments || finding.fragments.length == 0) return;

            var render = renderList[pageRange[0]];

            var fragment = null;
            var offset = null;
            var offsets = null;
            var lastFragment = null;
            var opt = {};

            var pushElement = function(fragment, offsets, area, opt){
                if(fragment.element._sType == "sText"){
                    action.addText(fragment.element, replaceExp, offsets, area, opt);
                }else if(fragment.element._sType == "sParagraph"){
                    action.addParagraph(fragment.element, offsets, area, opt);
                }
            }

            for(var area in finding.fragments){
                if(finding.fragments[area].length == 0) continue;

                offset = null;
                offsets = [];
                lastFragment = null;

                for(var i in finding.fragments[area]){
                    for(var j in finding.fragments[area][i]){
                        fragment = finding.fragments[area][i][j];

                        if(lastFragment == null || 
                            lastFragment.element === fragment.element){
                            offsets.push(fragment.offset);    
                        }else{
                            pushElement(lastFragment, offsets, area, opt);
                            offsets = [fragment.offset];
                        }

                        if(fragment.findStart){
                            fragment.offset.findStart = true;
                        }

                        lastFragment = fragment;

                        if(!offset) {
                            offset = fragment.offset;
                            offset.minPageIndex = offset.pageIndex;
                            offset.minRowIndex = offset.rowIndex;
                        }else {
                            if(offset.minPageIndex <= fragment.offset.pageIndex){
                                offset.minPageIndex = fragment.offset.pageIndex;

                                if(offset.minRowIndex < fragment.offset.rowIndex){
                                    offset.minRowIndex < fragment.offset.rowIndex
                                }
                            }
                        }
                    }
                }

                if(lastFragment != null){
                    pushElement(lastFragment, offsets, area, opt);
                }

                render.reformat(
                    action.getElements(area), 
                    offset, 
                    area, 
                    pageList, 
                    ssDict.sActionType.REPLACE);
            }
        }

        //页面内容发生改变，重置查找对象
        finding = {};

        this.invalidate({range: pageRange});      
    }
    
    /**
     * 绘制查找区域
     * @param {*} render 
     * @param {*} handle 
     * @returns 
     */
    var paintFindFragment = function(render, handle){
        if(!finding.fragments) return;
        
        let clearZones = {};
        let fragment = null;

        for(var i of areas){
            if(!finding.fragments[i]) continue;
            fragment = finding.fragments[i];

            if(render){
                if(fragment[handle]){
                    clearFindZone(render);
                    render.getPainter().drawFindZone(fragment[handle]);
                }
            }else{
                for(var i in fragment){
                    if(!renderList[i]) continue;
                    if(!clearZones[i]){
                        clearFindZone(renderList[i]);
                        clearZones[i] = true;
                    }
                    renderList[i].getPainter().drawFindZone(fragment[i]);
                }
            }
        }
    }

    /**
     * 为查询比较偏移量
     * @param {*} prev 
     * @param {*} offset 
     * @returns 
     */
    var isOffsetEqualForFind = function(prev, offset){
        if(!prev || !offset) return true;

        return prev.pageIndex == offset.pageIndex &&
               prev.rowIndex == offset.rowIndex &&
               prev.elementIndex == offset.elementIndex;
    }

    /**
     * 清除查找区域
     * @returns 
     */
    var clearFindZone = function(render){
        if(render){
            render.getPainter().clearFindZone();
        }else{
            for(var i in renderList){
                if(!renderList[i]) continue;
                renderList[i].getPainter().clearFindZone();
            }
        }
    }

    /**
     * 创建查找缓存
     * @param {*} cache 缓存
     * @param {*} pages 页面集合
     * @returns 
     */
    var createFindCache = function(cache, pages){
        cache = cache ? cache : {
            head: null,
            foot: null,
            body: null
        };

        var lastCache = {};
        var blockElements = [];

        pages.forEach((page, pageIndex)=>{
            page.forEach((row, rowIndex, type)=>{
                if(type != "body" && pageIndex > 1) return;

                if(!cache[type]){
                    cache[type] = {
                        texts: []
                    };
                    lastCache = {};
                }

                row.forEach((element, elementIndex)=>{
                    if(element.delete) return;
                    if(element._sType == "sText"){
                        if(element.innerText == null || 
                            element.innerText.length == 0 ||
                            !element.__texts) {
                            return;
                        }

                        if(lastCache.type != element._sType){
                            lastCache = {
                                type: "sText",
                                content: "",
                                offsets: []
                            };

                            cache[type].texts.push(lastCache);
                        }

                        var __text = element.__texts[pageIndex][rowIndex];

                        lastCache.offsets.push({
                            pageIndex: pageIndex,
                            rowIndex: rowIndex,
                            elementIndex: elementIndex,
                            start: lastCache.content.length,
                            end: minusStringLength(
                                lastCache.content.length + __text.length, 1)
                        });
                        lastCache.content += __text;
                    }else if(element._sType == "sParagraph"){
                        if(lastCache.type != "sText") return;

                        lastCache.offsets.push({
                            pageIndex: pageIndex,
                            rowIndex: rowIndex,
                            elementIndex: elementIndex,
                            start: lastCache.content.length,
                            end: lastCache.content.length + 1
                        });
                        lastCache.content += "\r\n";
                    }else if(element._sType == "sBreakline"){
                        if(lastCache.type != "sText") return;

                        lastCache.offsets.push({
                            pageIndex: pageIndex,
                            rowIndex: rowIndex,
                            elementIndex: elementIndex,
                            start: lastCache.content.length,
                            end: lastCache.content.length
                        });
                        lastCache.content += "\n";
                    }else if(element._sType == "sTable"){
                        if(blockElements.indexOf(element) > -1) return;
                        blockElements.push(element);

                        if(!cache[type].tables){
                            cache[type].tables = [];
                        }
                        
                        cache[type].tables.push(
                            createTableCache(element, {
                                pageIndex: pageIndex,
                                rowIndex: rowIndex,
                                elementIndex: elementIndex
                            })
                        );
                    }else if(element._sType == "sLayer"){
                    }
                });
            });
        });

        return cache;
    }

    /**
     * 创建表格内容缓存
     * @param {*} table 
     * @param {*} offset
     */
    var createTableCache = function(table, offset){
        var cell = null;
        var row = null;
        var cellCache = null;
        var cache = [];
        var cellOffset = null;
        var textOffset = null;

        for(var i = 0; i < table.getRowCount(); i++){
            row = table.getRows(i);

            for(var j = 0; j < table.getColCount(); j++){
                cell = row.getCells(j);
                if(cell.style && cell.style.display == "none") continue;
                cellCache = createFindCache({body: null}, cell.__pageList);
                if(cellCache.body){
                    cellOffset = ost.extractOffset(offset);
                    for(var k = cellOffset; k != null; k = k.next){
                        if(!k.next){
                            k.next = {
                                tableRowIndex: i,
                                tableColIndex: j
                            };
                            break;
                        }
                    }
                    cellCache.body.offset = cellOffset;
                }
                cache.push(cellCache);
            }
        }
        return cache;
    }

    /**
     * 将字符串长度减去指定长度
     * @param {*} strLength 
     * @param {*} minusLen 
     * @returns 
     */
    var minusStringLength = function(strLength, minusLen){
        var len = strLength - minusLen;
        len = len < 0 ? 0 : len;
        return len;
    }

    /**
     * 获取指定字符串在文本中的所有序号和数量
     * @param {*} text 被查找的文本
     * @param {*} str 待查找的字符串或正则表达式
     * @param {*} option 可选参数
     * @returns 
     */
    var findIndexInText = function(text, str, option) {
        var result = {
            len: null,
            indexList: []
        };

        if(!str){
            return result;
        }

        option = option ? option : {};

        if(option.useReg){
            var mode = "g";

            if(!option.caseSensitive){
                mode = "gi";
            }

            if(option.wholeWord){
                let replaceRules = {
                    1: {
                        start: 0,
                        end: 1,
                        exp: "^" + str + "\\s"
                    },
                    2: {
                        start: 1,
                        end: 0,
                        exp: "\\s" + str + "$"
                    },
                    3: {
                        start: 1,
                        end: 1,
                        exp: "\\s" + str + "\\s"
                    },
                    4: {
                        start: 0,
                        end: 0,
                        exp: "^" + str + "$"
                    },
                };
                
                var rule = null;

                for(var i in replaceRules){
                    rule = replaceRules[i];
                    
                    var regex = new RegExp(rule.exp, mode);
                    text.replace(regex, (match, index)=>{
                        result.indexList.push(index + rule.start);
                        if(result.len === null){
                            result.len = match.length - (rule.start + rule.end);
                        }

                        let start = index + rule.start + result.len;
                        let t = text.substring(start);
                        let ind = t.search(new RegExp(rule.exp, mode));
                        if(ind > -1){
                            result.indexList.push(start + ind + rule.start);
                        }

                        return match;
                    });
                }

                result.indexList.sort((a, b)=>a - b);
            }else{
                var regex = new RegExp(str, mode);
            
                text.replace(regex, (match, index)=>{
                    result.len = match.length;
                    result.indexList.push(index);
                    return match;
                });
            }
        }else{
            var txt = text;

            if(!option.caseSensitive){
                txt = text.toLowerCase();
                str = str.toLowerCase();
            }

            var prev = 0;
            var start = 0;
            var end = 0;

            while(true){
                start = txt.indexOf(str);
                
                if(start > -1){
                    end = start + str.length;
                    txt = txt.substring(end);
                    result.indexList.push(prev + start);
                    prev += end;
                }else{
                    break;
                }
            }

            result.len = str.length;
        }

        return result;
    }

    /**
     * 抽取偏移量
     * @param {*} target 
     * @param {*} deep 
     * @returns 
     */
    this.extractOffset = function(target, deep){
        return ost.extractOffset(target, deep)        
    }

    /**
     * 获取元素高度
     * @param {*} element 
     */
    this.getElementHeight = function(element){
        let rect = null;
        let height = 0;

        for(let i in element.__boundRect){
            rect = element.__boundRect[i];
            for(let j in rect){
                height += rect[j].height;
            }
        }

        return height;
    }
}